Tuesday, April 28, 2026

#1143 - AI DB MCP Server in conjunction with Private Agent Framework

Introduction 

According to the official doc - 

The Oracle Autonomous AI Database MCP Server is a managed, multi-tenant server designed to provide secure, standardized access to database tools and features through the Model Context Protocol (MCP). It provides an MCP server for each Autonomous AI Database, enabling AI agents and client applications to interact seamlessly with custom and built-in Select AI Agent tools using MCP APIs.

I want to try this out, especially in conjunction with the Private Agent Framework (PAF). The best starting point is the excellent live lab here.

The steps are simple - 
  • enable the MCP server on my ATP instance
  • do some initial setup - users, tables etc.
  • define tools, which will then be available via the MCP Server
  • Test the MCP Server in Claude
  • Add the MCP Server to PAF.
  • Create a simple workflow in PAF

Enabling ATP MCP Server

We enable this feature by adding the following tag - 

The MCP Server can be disabled, by setting the value as follows - 

{"name":"mcp_server","enable":false}

Simple! 

Now all I need is the instance ocid, before proceeding on to the next steps.

Initial Setup

Tools can be created for specific DB users, so let's create some - 

I login as hrm_user and create a couple of tables 


I now login as sales_user and create a couple of tables - 

So each user has their own tables, specific to their LOB.

Now to defining tools.

Define Tools




We will create the following tools for each of our 2 users -

Net, net, each user has the same set of tools, that will operate on each one's DB objects.

Leveraging the MCP Server from Claude 

Pre-req here is Node.js installed on my laptop - 

You also need the MCP Server endpoint; its format is as follows - 

https://dataaccess.adb.<region-identifier>.oraclecloudapps.com/adb/mcp/v1/databases/{database-ocid}

Again, simple!

In Claude, go to Settings --> Developers -->

Edit Config

and add the MCP Server config - 

{ "mcpServers": { "Autonomous_AI_database_mcp_server": { "description": "Database containing application-related data", "command": "npx", "args": [ "-y", "mcp-remote", "https://dataaccess.adb.{region-identifier}.oraclecloudapps.com/adb/mcp/v1/databases/{database-ocid}" ], "transport": "streamable-http" } } }

Now restart Claude - I will be asked to enter my DB credentials, this I do, signing in as hrm_user.
Validate the MCP Server is available - 






Click Configure -

Check out the tools - 

Back in chat -

Exposing the MCP Server to Private Agent Factory

Let's check out the config - 

Server URL is set to the MCP Server Endpoint -
https://dataaccess.adb.<region-identifier>.oraclecloudapps.com/adb/mcp/v1/databases/{database-ocid}


Token endpoint URL is set to 
https://dataaccess.adb.<yourRegion>.oraclecloudapps.com/adb/auth/v1/databases/<yourADB_OCID>/token


I leverage the MCP Server in a flow - 


Here's my simple flow - 

Let's run this agent - 

























Monday, April 27, 2026

#1142 - OIC Agentic AI Framework and Agent Input

Introduction 

The goal of this post is to detail how what we enter, in our OIC agent projects, surfaces in the prompts sent to the LLM.
 
Generally speaking, this is what is sent to the Agent/LLM - 
  • User Prompt – the specific request from the user e.g. approve the order with the number 123 for customer XYZ
  • System Prompt - establishes the core identity, tone, and global rules that persist across all conversations. In this case, this could include the order processing rules etc.
  • Tool Parameters - the specific data points required for the agent to execute a tool

Let's use the Resubmission Agent from the previous post; we begin by checking out the artifacts created -

Agent Pattern 

Note the guidelines I've entered here; these will flow into the System Prompt.

Agent Tools

In OIC, these are based on integrations.

Tool guidelines flow into the System Prompt. Tool description is also passed to the LLM, but through a different channel.

Here's an example from the Open AI API docs -

# 1. Define your tool
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather in a given location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City and state"},
                },
                "required": ["location"],
            },
        },
    } 
] 

Ergo, the data you enter for tool description, as well as the data you enter for parameter description, is passed to the LLM.

# 2. Pass tools to the API
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "What's the weather in London?"}],
    tools=tools,
    tool_choice="auto"
) 


Agent

The agent definition contains Role and Guidelines.


These also flow into the System Prompt.


User Prompt

This input is the user prompt

Let's run the agent - 

First part of the System Prompt includes the Agent Role and Guidelines, then we see the Pattern guidelines. 


Then we see the User Prompt

Then we see the Tool Guidelines -


Now the thinking begins -

Tool is invoked - 

So what happens when we continue the conversation? Let's check that out via a new conversation. I begin by ensuring we have an error -

I run the agent - 

I continue the conversation - 



I now ask - what was the exact time of the error?

As you can see, the new user prompt is added to the audit flow, which mirrors the data sent to the LLM, apart from the tools data.

Net, net - in such a conversation, we can have multiple user prompts sent to the LLM, but system prompt data is pushed only once.



 






 





 



Thursday, April 23, 2026

#1141 - OIC Agent for error resubmission

Introduction 

This is a simple demo on leveraging OIC Agents to monitor and resubmit errors. The business case is as follows, orders are received and need to be processed in a timely manner. The order processing is done by an asynchronous integration, I call it ASYNC_MAIN; the actual processing is done by 2 synchronous integrations, SYNC1 and SYNC2. 

SYNC1 and SYNC2 are 2 steps in the order process. Naturally, if an error occurs in SYNC2, by resubmission, we don't want SYNC1 executed a second time. To ensure this, I have added a WAIT to ASYNC_MAIN, just after the invoke of SYNC1. This will ensure the process state is dehydrated, and, in case of resubmission, SYNC1 will not be re-executed. 

Back to the business use case, any order processing errors in ASYNC_MAIN, need to be fixed and resubmitted ASAP, ergo, I need to monitor for errors in ASYNC_MAIN, I also need the ability to resubmit failed instances of ASYNC_MAIN. Here is the flow - 






The error will be generated, when I enter an order for an invalid product, in my case, the non-existent iCar. To ease testing, I have added a lookup to the project, that contains the product value. This allows me to easily mimic fixing the error, before resubmission. 



The next component is a DB table on ATP - 

Sample DDL -

CREATE TABLE "NIALLC"."ERRORED_FLOWS"   ( "INSTANCEID" VARCHAR2(30 BYTE) COLLATE "USING_NLS_COMP", "PROJECTNAME" VARCHAR2(50 BYTE) COLLATE "USING_NLS_COMP", "INTEGRATIONNAME" VARCHAR2(50 BYTE) COLLATE "USING_NLS_COMP"   )  DEFAULT COLLATION "USING_NLS_COMP" ;

ALTER TABLE "NIALLC"."ERRORED_FLOWS" MODIFY ("INSTANCEID" NOT NULL ENABLE);

ALTER TABLE "NIALLC"."ERRORED_FLOWS" MODIFY ("PROJECTNAME" NOT NULL ENABLE);

ALTER TABLE "NIALLC"."ERRORED_FLOWS" MODIFY ("INTEGRATIONNAME" NOT NULL ENABLE); 

On error, a row will be written to this table - 


The flow, with instance id, 2HVm-j8dEfG8Ab8Y-P4nAQ, errors out. 


Let's process a second order, with the same invalid product, iCar.


The flow, with instance id, O6f-Sj8eEfGQlVci_IGJCQ, errors out.

The result - 2 rows in my errors table -

Using the OIC Factory API to monitor errors 

Back to the business use case, we need to monitor errors in ASYNC_MAIN. This we can do by monitoring the OIC Observability page, but we want to automate this, correct? Here's where the OIC factory api comes into play. Here is the api call to monitor errors in this integration - 

https://design.integration.yourRegion.ocp.oraclecloud.com/ic/api/integration/v1/monitoring/errors?integrationInstance=yourOICInstance&q={timewindow: '1h', projectCode: 'AA_RESUBMIT_AGENT',code: 'ASYNC_MAIN'}

The response contains lots of interesting data, check out the excerpt here -

{
    "dataFetchTime": "2026-04-23T14:13:26.594+0000",
    "items": [
        {
            "creationDate": "2026-04-23T14:10:50.525+0000",
            "currentTraceLevel": "Debug",
            "errorCode": "500",
   ...
\"faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Invalid Product: iCar}\",\n    \"errorPath\" : \
... \"errorCode\" : \"ERR-001\"\n  } ]\n}.The 500 Internal Server Error is a 
...
                {
                    "detailErrorMessage": "<fault xmlns=\"http://xmlns.oracle.com/cloud/oic/gen3fault\"><traceId>05c9604058916bdfd251f9e87336055a</traceId>
...
                    "errorCode": "500",
                    "errorLocation": "Re-throw Fault",
                    "errorMessage": 
...
 cause: {Invalid Product: iCar}\",\n  \"errorCode\" : \"500\",\n  \"errorDetails\" : [ {\n    \"type\" : \"UnMappedFault:\",\n    \"instance\" : \"NA\",\n    \"title\" : \"faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Invalid Product: iCar}\",\n    \"errorPath\" : \"<![CDATA[<location xmlns=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\">mcube</location>\\n]]>\",\n    \"errorCode\" : \"ERR-001\"\n  } ]\n}
...
            "errorLocation": "Re-throw Fault",
            "errorMessage": "<![CDATA[{\n  \"type\" : \"http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1\",\n  \"title\" : \"ERR-001\",\n  \"detail\" : \"faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Invalid Product: iCar}\",\n  \"errorCode\" : \"500\",\n  \"errorDetails\" : [ {\n    \"type\" : \"UnMappedFault:\",\n    \"instance\" : \"NA\",\n    \"title\" : \"faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Invalid Product: iCar}\",\n    \"errorPath\" : \"<![CDATA[<location 
...
            "instanceId": "O6f-Sj8eEfGQlVci_IGJCQ",
            "instanceReportingLevel": "Debug",
            "integrationDeleted": false,
            "invokedBy": "niall.commiskey@oracle.com",
            "isDataAccurate": true,
      ... 
             "primaryName": "orderNr",
            "primaryValue": "2113",
            "projectCode": "AA_RESUBMIT_AGENT",
            "projectName": "AA-Resubmit-Agent",
            "recoverable": true,
            "replayable": false,
            "replayed": false,
            "retryCount": 0
        },
        {
            "creationDate": "2026-04-23T14:08:04.154+0000",
            "currentTraceLevel": "Debug",
            "errorCode": "500",
...
            "errorItems": [
                {
                    "detailErrorMessage": "
... \"ERR-001\",\n  \"detail\" : \"faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Invalid Product: iCar}\",\n  \"errorCode\" : \"500\",\n  \"errorDetails\" : [ {\n    \"type\" : \"UnMappedFault:\",\n    \"instance\" : \"NA\",\n    \"title\" : \"faultName: 
... 
{                "recoverable": true,
                    "retryCount": 0,
                    "state": "MCUBE_ACTIVITY_RECOVERY_REQUIRED",
                    "status": "FAILED"
                }
            ],
     ...
faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Invalid Product: iCar}\",\n    \"errorPath\" : \"<![CDATA[<location xmlns=\\\"http://schemas.xmlsoap.org/soap/envelope/\\\">mcube</location>\\n]]>\",\n    \"errorCode\" : \"ERR-001\"\n  } ]\n}.
...
            "faultId": "6tIF0D8dEfGez3_SZkbBOA",
            "id": "2HVm-j8dEfG8Ab8Y-P4nAQ",
            "instanceId": "2HVm-j8dEfG8Ab8Y-P4nAQ",
           ...
          "primaryName": "orderNr",
            "primaryValue": "2112",
            "projectCode": "AA_RESUBMIT_AGENT",
            "projectName": "AA-Resubmit-Agent",
        ...
        }
    ],
   ...
    "timeWindow": "1",
    "totalRecordsCount": 2,
    "totalResults": 2
}

Interesting fields in red. 

Our integration, get Error Details, will use this api. 

Using the OIC Factory API to resubmit errors 

Here is the api call I use - 

Now to my integrations, which will leverage the factory api - 

The Resubmit Failed Flows integration is as follows; I also include the details of get Error Details - 




I expose these 2 integrations as tools to my agent - 

Let's try out the agent -

In the last hour, there were 2 errors for the integration ASYNC_MAIN in the project AA_RESUBMIT_AGENT.

What caused these errors? 

The errors were caused by an internal server error with HTTP status code 500. Specifically, the faultName is "ns0:APIInvocationError," and the reason provided is related to an internal server problem with the message: "faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Invalid Product: iCar}."


This indicates that the underlying issue causing the errors was invoking an external service that encountered an internal error related to an invalid product identified as "iCar."


Was order number 2112 affected?

Yes, the order number 2112 was affected. It is associated with one of the errored instances in the last hour for the integration ASYNC_MAIN in the project AA_RESUBMIT_AGENT.


"The best revenge is to be unlike him who performed the injury." - Marcus Aurelius

Let's resubmit, but, before we do so, let's set the lookup value to iBike.

I resubmit via the agent - 

The database table no longer has any rows; the delete being done in the RESUBMIT integration -

I validate in OIC Observability

Naturally, we could have a scheduled integration that uses the new OIC AI Agent native action to ensure these resubmits are done on a regular basis, based on business needs. That I leave up to you!

Summa Summarum


This is a simple use case for an agent, but it does address the business use case and does save lots of time and manual effort. Over time, you may see such functionality OOTB in OIC Observability, but, up until then, this is a viable alternative. You can get project export here.