• Fun and games with OCI DRGs, RPCs and VPNs – attempting to connect from On-Prem to a peered tenant πŸ”Œ

    This is probably my most niche-ist post ever – however if it helps at least one person then it was worth writing up!

    I have an OCI Tenant (Tenant A), which has a Site-to-Site VPN connection configured between my On-Premises network (my house 🏠) and Tenant A, this enables me to connect to resources within my tenant using their private IP addresses rather than using a Bastion/Jump Server – for example I can SSH directly into VM instances.

    This has worked perfectly well for the last couple of years, recently I provisioned a second OCI Tenant (Tenant B) and I wanted to configure connectivity between Tenant A and B, after some research I selected the option of connecting the networks in Tenant A and Tenant B using a Remote Peering Connection (RPC) between the Dynamic Routing Gateways (DRGs) in each tenancy.

    There are two other options to achieve this, however as I like a challenge, I picked the most difficult of the three options – this is also because the customer I’m working with, will likely choose the RPC option too.

    To set this up, I used the step-by-step guide available here, which is excellent – I found it far better than the official documentation.

    Once I had this all setup, I had the following architecture.

    Based on my initial testing I could now do the following:

    • Connect from my On-Premises network to resources in Tenant A βœ…
    • Connect from Tenant A to resources in Tenant B βœ…
    • Connect from Tenant B to resources in Tenant A βœ…

    I couldn’t however connect from On-Premises to resources in Tenant B ❌.

    In the real-world (outside of my lab), it would be essential (in most cases) to have the ability to connect from On-Premises to all OCI tenancies – in particular when they are connected like this.

    After much head-scratching and reading documentation – which is always a last resort! I figure out the problem(s) and managed to resolve the issue with my On-Premises network being unable to connect to Tenant B.

    This was resolved by doing the following in Tenant A (no changes were required for Tenant B).

    • Created 3 x Import Rule Distributions (On-Prem/RPC/VCN).
    • Created 3 x Route Tables (On-Prem/RPC/VCN), associating each of these new Route Tables with the respective new Import Rule Distributions.
    • Associated each Route Table with the respective Attachments (replacing the OOTB configuration).
      • On-Prem > IPSec Tunnel Attachment
      • RPC > Remote Peering Connection Attachment
      • VCN > VCN Attachments

    Here are the Import Route Distributions that I needed to create:

    On-Prem Import Routes: This will enable On-Prem to see all of the routes from the VCNs and Remote Peering Connection.

    Remote Peering Connection Import Routes: This will enable the RPC to see all of the VCNs and IPSec tunnel (which is the Site to Site VPN).

    VCN Import Routes: This enables all VCNs to see all of the VCNs, RPCs and IPSec Tunnel.

    Here are the Route Tables with the mapping to the Import Rule Distributions On-Prem/RPC/VCN:

    Here are the Attachments with the association to the respective Route Tables.

    As a side note, if you are using a FastConnect rather than a Site-to-Site VPN for On-Premises to OCI connectivity the tweaks you’ll need to make to the configuration are:

    • Replace IPSec Tunnel with Virtual Circuit in the Import Rules
    • The On-Prem Route Table should be associated with the Virtual Circuit Attachment rather than IPSec Tunnel Attachment.

  • OCI Generative AI Agent returns a “NotAuthorizedOrNotFound” error when invoking a SQL tool βŒ

    If you run into the following error when using an OCI Generative AI Agent that attempts to use a SQL Tool

    User Error: Failed to execute DB query with Error – NotAuthorizedOrNotFound: Authorization failed or requested resource not found with http status 404

    If you are like me, the reason for this error is that you didn’t read the manual 🀦, this error is typically returned because the Generative AI Agent service does not have permission to the Database Connection and Key Vault – which is required to connect to the database and run the query generated by the agent.

    The fix for this is to create a policy that grants the necessary permissions to the Generative AI Agents service – which is documented here (below for reference too).

    Allow any-user to use database-tools-connections in compartment <compartment-name> where request.principal.type='genaiagent'
    
    Allow any-user to read database-tools-family in compartment <compartment-name> where request.principal.type='genaiagent'
    
    Allow any-user to read secret-family in compartment <compartment-name> where request.principal.type='genaiagent'
  • Using model aliases in OCI Gen AI πŸ§ 

    One thing I’ve been caught out with in the past with OCI Gen AI is when an AI model gets retired and my apps that specifically call the model start to fail as the model is no longer available!

    The fix for this isn’t particularly difficult, it’s just a case of updating the code to point to the new model name (via model_id), this can be quite stressful though when you are about to deliver a demo to a customer 😫.

    I was really pleased to see the introduction of model aliases (Cohere-only at this time), so rather than using a hardcoded reference to a specific model version you can now use the following aliases, which will always point to the latest version of the Cohere Command R and Coheren Command R+ models.

    cohere.command-latest points to cohere.command-r-08-20204
    cohere.command-plus-latest points to cohere.command-r-plus-08-2024

    Full details are included in the documentation πŸ“–.

  • Oracle Autonomous Database – ORA-20400: Request Failed with status HTTP 400 when connecting to Gen AI

    Yesterday I added a new AI profile to an Oracle Autonomous Database using the Database Actions UI, when testing this new profile I received the following error:

    This appears to be caused by Database Actions not creaing the profile correctly, the fix was to manually create the profile using the following SQL statement:

    BEGIN
      DBMS_CLOUD_AI.CREATE_PROFILE(
          profile_name => 'TestProfile',
          attributes   => '{"provider": "oci",
                            "credential_name": "TESTCREDS",
                            "object_list": [{"owner": "ADMIN"}],
                            "model": "cohere.command-r-plus-08-2024",
                            "region": "uk-london-1"
                           }');
    END;
    /
    

    This created a profile named TestProfile that uses the existing saved credentials named TESTCREDS to connect to the cohere.command-r-plus-08-2024 model in the uk-london-1 region – for some reason the Database Actions UI hardcodes the region to Chicago (which is another reason to create the profile manually!)

    In addition to this, it gives the profile access to all objects owned by the account named ADMIN.

    Obvouisly, you’ll need to update these with the relevant values for your environment.

    After doing this, it was able to successfull connect:

  • Error building a container when using the OCI Cloud Shell πŸ«™

    This afternoon I was using the OCI Cloud Shell to build a container to be pushed to the OCI Container Registry which I was then going to create an OCI Container Instance from. This is something that I’ve done countless times without any issues, as I was short of time (I’m going on holiday tomorrow) as is typical, anything that could go wrong, did 😭.

    When running the following command from the OCI Cloud Shell to build the container.

    docker build --tag container-name .
    

    It returned the following error (interesting bits in bold).

    Error: committing container for step {Env:[PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LANG=C.UTF-8 GPG_KEY=E3FF2839C048B25C084DEBE995E310250568 PYTHON_VERSION=3.9.21 PYTHON_SHA256=3126f59592c9b0d7955f2bf7b081fa1ca35ce7a6fea980108d752a05bb1] Command:run Args:[pip3 install -r requirements.txt] Flags:[] Attrs:map[] Message:RUN pip3 install -r requirements.txt Heredocs:[] Original:RUN pip3 install -r requirements.txt}: copying layers and metadata for container “4aa0c966251fa75dac10afc257b8c8d62aae50c45eb5dd1157d3c1cae0208413”: writing blob: adding layer with blob “sha256:5699f359aa00daa8a93b831b478fea1fe7c339396e532f13e859fb4ef92fd83f”: processing tar file(open /usr/local/lib/python3.9/site-packages/oci/addons/adk/__pycache__/agent_client.cpython-39.pyc: no space left on device): exit status 1

    After much Googling (without much luck I may add!) I had a brainwave – the OCI Cloud Console only provides 5GB storage as per the documentation – perhaps I’d hit the storage limit πŸ€”:

    It turned out that the majority of the storage consumed was by Docker / Podman (as a side note the Cloud Shell now uses Podman, however the Docker commands are aliased to it, so you can continue to use them).

    So……it looked like I needed to do some housekeeping 🧹.

    To identify the storage used by Docker / Podman, you can run the following command:

    docker system df
    

    Which returned the following:

    To free up some space I ran the following command (which is a little brute force, I may add πŸ”¨):

    docker system prune -a
    

    Using my YOLO approach, I selected y to continue which worked its magic and free’d up some space (please take heed of the warnings ⚠️).

    I then had plenty of free space and could build the container successfully βœ…

    I can now enjoy my holiday, safe in the knowledge that I managed to fix this issue πŸ—ΊοΈ.

  • Calling a Custom API from an OCI Generative AI Agent πŸ§ 

    In this short video, I step through how to create an Oracle Generative AI Agent and then configure a tool within the Agent to connect to a public API that performs URL shortening. This uses the new (as of July 2025) API Endpoint Calling Tool functionality within the Generative AI Agents Service.

    This allows users to ask the agent to shorten a URL, the agent then calls a public API that can shorten URLs (https://cleanuri.com/docs) and returns a shortened URL to the user.

  • Getting the output of a SQL tool in an OCI Gen AI Agent πŸ“Š

    The Generative AI Agent service in OCI recently added the ability to add a SQL Tool, this enables an agent to generate a SQL query and optionally run the query against a database and return the results of the query to the agent πŸ€–. I created a short video that steps through how to use a SQL Tool βš’οΈ with an agent, which can be found here πŸ“Ό.

    More recently (mid-July 2025) the SQL Tool has been further enhanced so that responses include the following:

    • The raw output of the SQL query
    • A conversational “LLM style” response

    Previously a SQL Tool would only return the raw output of the SQL query, I found this quite useful as I could use Python packages such as matplotlib to visualise results, as of mid-July responses from the agent also include an LLM style conversational response, for example (taken from my agent that queries a database of bird sightings πŸ¦…):

    Raw Output of SQL Query

    Conversational LLM Style Response

    I’ve put together a short Python script that demonstrates how to get access to this data from a response, I typically use Streamlit as a front-end for the demo agents that I build, however to keep things simple, we’ll use the good old “shell” for this demo!

    Here is the script –

    import oci
    textinput = "what were the 3 most popular birds in 1997"
    config = oci.config.from_file(profile_name="DEFAULT")
    service_ep = "https://agent-runtime.generativeai.uk-london-1.oci.oraclecloud.com"
    agent_ep_id = "ocid1.genaiagentendpoint.oc1.uk-london-1.xwywwkz7bn5f5aogazpvkijnoj2u75yadsq"
    generative_ai_agent_runtime_client = oci.generative_ai_agent_runtime.GenerativeAiAgentRuntimeClient(config,service_endpoint=service_ep)
    create_session_response = generative_ai_agent_runtime_client.create_session(
        create_session_details=oci.generative_ai_agent_runtime.models.CreateSessionDetails(
            display_name="Session",
            description="Session"),
        agent_endpoint_id=agent_ep_id)
    sess_id = create_session_response.data.id
    response = generative_ai_agent_runtime_client.chat(
        agent_endpoint_id=agent_ep_id,
        chat_details=oci.generative_ai_agent_runtime.models.ChatDetails(
            user_message=textinput,
            session_id=sess_id))
    output = response.data.traces[3].output
    output = eval(output)
    sql_response = output["result"]
    print("")
    print("SQL Response: " + str(sql_response))
    text_response = response.data.message.content.text
    print("")
    print("Text Response: " + str(text_response))
    

    To use this script you’ll need to update the following:

    Finally make sure you have the latest version of the OCI SDK for Python, to upgrade to the latest version run the following command –

    pip3 install oci --upgrade

    When run the output should look something like this:

    Here is an example of how I’ve used matplotlib (within a Streamlit front-end) to visualise results using the raw output of the SQL query.

    As you can see below, it returns the conversational response, I then take the raw SQL output and use matplotlib to make it look pretty πŸ’„ – I may put together a post on this too.

    Thanks for reading!

  • Using Zero Trust Packet Routing (ZPR) to Secure OCI β›”️

    I’ve put together a short video that demonstrates how to configure OCI Zero Trust Packet Routing (ZPR) to secure resources within a Virtual Cloud Network (VCN).

    For this, I will be using the following topology:

    This includes a single VCN that contains 4 x subnets.

    • 1 x Public Subnet – containing a Jump Server that is accessible directly over the Internet.
    • 3 x Private Subnets – containing a Client PC, Load Balancer and 2 x Web Servers.

    The intent of this demo is to create a ZPR configuration that supports the following access βœ… – but nothing more ❌

    • SSH access from the Internet to the Jump Server βœ…
    • SSH access from the Jump Server > Client PC βœ…
    • HTTP access from the Client PC > Load Balancer βœ…
    • HTTP access from the Load Balancer > Web Servers βœ…

    This means that the following should not be permitted:

    • Any access from the Jump Server > Load Balancer or Web Servers ❌
    • Any access from the Client PC > Web Servers ❌
    • Any access from the Web Servers > Client PC ❌

  • SSH to a Compute Instance in OCI using a Bastion πŸ–₯️

    This short video demonstrates how to connect to a compute instance in OCI that does not have a public IP address using the OCI Bastion service πŸ”.

    If you’d like to use OCI Bastion to connect to a Windows compute instance πŸ–₯️, check out the following blog post which includes a step-by-step guide πŸ“‹.

  • Locking down OCI using a Security Zone πŸ”

    This short video (a whole 4 mins! ⏱️) explains the value of using OCI Security Zones and steps through the process of creating a Security Zone that blocks creation of public Object Storage Buckets.