Skip to main content

Implement - Invoice Status Assistant for Fusion ERP

Calculating read time…
🤖
AI Agent
Invoice Assistant
🔧
Tool
get_invoice_status
📝
Prompt Template
AP Specialist
⚙️
OIC Integration
Fusion ERP REST
🧪
Testing
Real invoice inputs
🚀
Deployment
DEV → TEST → PROD

📋 Section 1: Business scenario and solution overview

Every Accounts Payable team in a company using Oracle Fusion ERP faces the same daily question, asked hundreds of times: "What is the status of my invoice?" A supplier calls. A finance analyst checks. A manager asks in a meeting. Each time, someone logs into Fusion, navigates to the AP module, searches by invoice number, and reads back the status. It is repetitive, slow, and a waste of skilled time.

💡 The business goal: A business user types — "What is the status of invoice INV100234?" — and gets back an accurate, business-friendly response in seconds, without logging into Fusion, without writing a query, and without any human lookup. The AI Agent handles it all.

🗣️ The exact user journey we are building

👤 User asks: "What is the status of invoice INV100234?"
⬇️
🧠 Agent thinks: "This is an invoice status query. I have the get_invoice_status tool. I will call it with invoice_number = INV100234."
⬇️
⚙️ Tool executes: Calls OIC integration → OIC calls Oracle Fusion AP REST API → Returns invoice data in SUMMARY format.
⬇️
💬 Agent responds: "Invoice INV100234 was submitted by Acme Supplies on 5-Jun-2026 for ₹1,24,500. Current status: Approved — Pending Payment. Payment is scheduled for 20-Jun-2026. No action is required from your side."
✅ What changes for the business
AP team stops answering repeated status queries. Suppliers get instant self-serve answers. Finance managers get status in seconds during meetings. Zero logins to Fusion for routine lookups.
🎯 What you will build
One AI Agent in OIC Gen3 with one tool, one prompt template, and one OIC integration connecting to Oracle Fusion ERP. Fully deployed and production-ready by the end of this lab.
⏱️ Time to complete
Approximately 45 minutes. 15 min for OIC integration. 10 min for Tool + Prompt Template. 10 min for Agent. 10 min for Testing + Deployment.

🏗️ Section 2: Solution architecture

Before touching OIC, every architect draws the solution. Here is the complete architecture of what we are building.

🏗️ Invoice Status Assistant — complete solution architecture
┌─────────────────────────────────────────────────────────┐
│              BUSINESS USER / CHATBOT CHANNEL            │
│      "What is the status of invoice INV100234?"         │
└─────────────────────┬───────────────────────────────────┘
                      │ REST POST (goal + invoice number)
                      ▼
┌─────────────────────────────────────────────────────────┐
│              OIC Gen3 AI AGENT STUDIO                   │
│  ┌──────────────────────────────────────────────────┐  │
│  │    INVOICE STATUS AGENT (ReAct Loop)             │  │
│  │  ┌─────────────┐  ┌───────────────────────────┐ │  │
│  │  │ OCI GenAI   │  │  Prompt Template          │ │  │
│  │  │ (LLM Brain) │  │  (AP Specialist Rules)    │ │  │
│  │  └─────────────┘  └───────────────────────────┘ │  │
│  │           │ THINK: call get_invoice_status        │  │
│  └───────────┼───────────────────────────────────────┘  │
│              │ TOOL CALL                                │
│  ┌───────────▼───────────────────────────────────────┐  │
│  │    TOOL: get_invoice_status                       │  │
│  │    Input:  { invoice_number: "INV100234" }        │  │
│  │    Output: SUMMARY { status, amount, supplier.. } │  │
│  └───────────┬───────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                      │ REST Trigger (invoice_number)
                      ▼
┌─────────────────────────────────────────────────────────┐
│          OIC INTEGRATION: GET_INVOICE_STATUS            │
│   REST Trigger → Map → Fusion AP Adapter → Map         │
│   → SUMMARY Transform → Return JSON                    │
└─────────────────────┬───────────────────────────────────┘
                      │ Oracle Applications Adapter (OAuth)
                      ▼
┌─────────────────────────────────────────────────────────┐
│          ORACLE FUSION ERP (Accounts Payable)           │
│   REST API: /fscmRestApi/resources/11.13.../invoices    │
│   Returns: Full invoice JSON (status, amount, dates...) │
└─────────────────────────────────────────────────────────┘
Layer 1 — User Channel
Any REST client, chatbot, or OIC trigger. Sends natural language + context.
Layer 2 — AI Agent
OCI GenAI LLM + Prompt Template. Decides WHAT to call and WHEN.
Layer 3 — Tool
Registered capability the Agent invokes. Defined with name, description, schema.
Layer 4 — OIC Integration
The actual Oracle integration flow. Connects to Fusion. Returns trimmed data.
Layer 5 — Fusion ERP
Oracle Fusion Accounts Payable REST API. The authoritative system of record.

🎭 Section 3: Agent pattern selection — why we choose ReAct

OIC Gen3 supports different agent patterns. You must choose the right one before creating the agent. The wrong pattern wastes iterations and produces unpredictable output.

💡 What is an Agent Pattern? An agent pattern is the recipe that tells the agent how to think. It defines the decision loop — does the agent think step by step? Does it plan upfront? Does it just answer directly? Choosing the right pattern is like choosing the right cooking method before entering the kitchen.
❌ Plan-and-Execute (not for us)
Creates a full plan upfront before acting. Good for multi-step research tasks. Overkill for a single-tool lookup. Adds unnecessary latency for our use case.
❌ Chain-of-Thought Only (not for us)
Good for reasoning through text problems without actions. Cannot call tools. Our agent must call get_invoice_status — so pure chain-of-thought is insufficient.
✅ ReAct — our choice
Reason + Act. The agent thinks, acts (calls a tool), observes the result, adapts. Perfect for query-and-respond workflows like invoice status lookup. Efficient, traceable, and exactly right for our use case.

🔄 Why ReAct fits invoice status lookup perfectly

// ReAct Pattern Recipe for Invoice Status Agent

THINK:   "User wants invoice status. I have get_invoice_status tool.
          I need invoice_number = INV100234. I will call the tool."
            ↓
ACT:     Calls get_invoice_status(invoice_number="INV100234")
            ↓
OBSERVE: Tool returns: {status:"Approved",amount:124500,supplier:"Acme"...}
            ↓
THINK:   "I have the data. Goal is complete. I will now compose
          a clear business-friendly response."
            ↓
RESPOND: "Invoice INV100234 from Acme Supplies is Approved..."
ReAct setting Value for this lab Why
max_iterations5One tool call needed. 5 is more than enough. Prevents runaway loops.
temperature0.1Invoice data must be factual. Low temperature = deterministic, grounded responses.
max_tokens500Invoice status responses are short. 500 tokens is generous for a business reply.
session_timeout60 secondsSingle tool call. Should complete in under 15 seconds. 60s is a safe ceiling.
memory_enabledfalseEach invoice query is independent. No session memory needed for this use case.

⚙️ Section 4: Build the OIC Integration first — the tool's engine

The golden rule: build the integration before registering the tool. The tool needs a tested, working OIC endpoint to point at. We start here.

🚨 Pre-requisite check: Before step 1 below, confirm you have: (1) An OIC Gen3 instance running. (2) An Oracle Fusion ERP instance with AP invoices. (3) A Fusion OAuth client ID and secret stored in OCI Vault. (4) Network connectivity between OIC and Fusion. If any of these are missing, set them up before continuing.

📋 Step-by-step: create the OIC Integration

1
Navigate to OIC Integrations
Open OIC Gen3 console → Click Integrations in the left menu → Click Create → Select Application integration type → Name it: GET_INVOICE_STATUS → Description: "Retrieves invoice status from Oracle Fusion AP for a given invoice number" → Click Create.

✅ Verify: You should see a blank integration canvas with two endpoints — a trigger (left) and invoke (right).
2
Configure the REST Trigger (entry point)
On the canvas, click the Trigger (left side) → Choose REST Adapter → Configure:
  • Endpoint Name: GetInvoiceStatus
  • Relative URL: /invoice/status
  • HTTP Method: POST
  • Request Body → JSON Sample:
{ "invoice_number": "INV100234" }
  • Response Body → JSON Sample:
{ "invoice_number": "INV100234", "status": "Approved", "supplier_name": "Acme Supplies", "invoice_amount": 124500, "currency": "INR", "invoice_date": "2026-06-05", "payment_due_date": "2026-06-20", "gl_posting_status": "Posted", "message": "" }
Click Done.

✅ Verify: Trigger endpoint appears on canvas in green. The REST URL is visible.
3
Add a Fusion AP Invoke (call Fusion ERP)
Click + on the canvas → Choose Oracle Applications Adapter → Select your pre-configured Fusion connection → Configure:
  • Action: Query | Module: Financials → Payables → Invoices
  • Operation: GET /payablesInvoices/{InvoiceId}

If searching by invoice number (not internal ID), use:
  • REST URL: /fscmRestApi/resources/11.13.18.05/payablesInvoices?q=InvoiceNumber={invoice_number}

Click Done. The invoke appears connected to the trigger.

✅ Verify: Canvas shows REST Trigger → Fusion AP Invoke. A yellow mapping icon appears between them.
4
Map the request (Trigger Input → Fusion Query)
Click the mapping icon between Trigger and Fusion Invoke → OIC Mapper opens.

Map: $GetInvoiceStatus.request.body.invoice_number → Fusion query parameter InvoiceNumber in the URL template.

XSLT expression for the query parameter:
concat("InvoiceNumber=", $invoiceNumber)
Click Validate then Close.

✅ Verify: Mapping shows a green checkmark. No red unmapped required fields.
5
Map the response — CRITICAL: return a SUMMARY payload
Click the mapping icon between Fusion Invoke and Trigger Response → Map only these 8 fields:
// Map ONLY these 8 fields — ignore the other 200+ Fusion fields
invoice_number   ← InvoiceNumber
status           ← ValidationStatus
supplier_name    ← SupplierName
invoice_amount   ← InvoiceAmount
currency         ← InvoiceCurrencyCode
invoice_date     ← InvoiceDate
payment_due_date ← PaymentsDueDate
gl_posting_status← AccountingStatus
message          ← concat("", "") // empty unless error
Why only 8 fields? Fusion returns 200+ JSON fields per invoice. Passing all of them burns context window tokens and inflates LLM cost. The agent only needs these 8 to answer any invoice status question — this is the SUMMARY pattern.

✅ Verify: Response mapping shows only 8 fields mapped. Validate with no errors.
6
Add a Fault Handler for invoice not found
Click the Fault Handler tab → Add a global fault handler → Assign activity inside it:
invoice_number = $invoiceNumber (from request)
status         = "NOT_FOUND"
message        = concat("Invoice ", $invoiceNumber, " not found in Fusion ERP.")
// All other fields = empty string ""
This ensures the tool always returns structured JSON even when the invoice doesn't exist — the agent can then give a clear "not found" response instead of failing.

✅ Verify: Fault handler scope is visible on canvas. Assign activity is inside it.
7
Activate and test the OIC Integration
Click Save → Click Activate → Tracing level: Audit → Click Activate.

Once active, click Test → Select the trigger endpoint → Enter test body:
{ "invoice_number": "INV100234" }
Click Run. Check the response.

✅ Expected response:
{
  "invoice_number":    "INV100234",
  "status":            "Approved",
  "supplier_name":     "Acme Supplies Ltd",
  "invoice_amount":    124500,
  "currency":          "INR",
  "invoice_date":      "2026-06-05",
  "payment_due_date":  "2026-06-20",
  "gl_posting_status": "Posted",
  "message":           ""
}
Copy the integration's REST endpoint URL. You will need it in the Tool step.

✅ Verify: Response contains all 8 SUMMARY fields with real Fusion data. Status = HTTP 200.

📝 Section 5: Create the Prompt Template — the agent's rulebook

The Prompt Template defines who the agent is, what it knows, how it should reason, and exactly what format its answers must follow. We create and upload this before creating the Agent in OIC Gen3.

💡 Why create this first? In OIC Gen3, the Agent configuration points to a Prompt Template stored in OCI Object Storage. You must upload the template before you can configure the Agent to use it.

📝 Step-by-step: write and upload the Prompt Template

1
Create the Prompt Template text file
Open any text editor. Create a file named invoice_status_agent_prompt_v1.0.txt

Copy and paste this exact template:
## IDENTITY
You are InvoiceBot, an Oracle Fusion Accounts Payable specialist at InfraGroup India.
You help business users check invoice status quickly and accurately.
Today's date: {{current_date}} | Requested by: {{user_name}}

## YOUR ONLY JOB
Answer questions about invoice status using the get_invoice_status tool.
You do NOT answer questions about GL, payroll, HR, purchase orders, or any
topic outside Accounts Payable invoices. Politely decline and redirect.

## HARD RULES — NEVER BREAK THESE
RULE 1: NEVER state invoice data you did not receive from the tool. If the tool
         returns no data, say the invoice was not found. Do not guess or invent data.
RULE 2: ALWAYS call get_invoice_status before answering any invoice status question.
         Never answer from memory or prior context.
RULE 3: Extract the invoice number from the user's message exactly as written.
         Do not modify it. INV100234, inv100234, and Inv 100234 are the same — use INV100234.
RULE 4: If the tool returns status = "NOT_FOUND", tell the user the invoice number
         was not found and ask them to verify the number. Do not speculate why.
RULE 5: Format currency amounts with commas and the currency code.
         Example: INR 1,24,500 not 124500.

## REASONING STEPS (follow in order)
STEP 1: Read the user message. Extract the invoice number.
STEP 2: Clean and standardise the invoice number (uppercase, no spaces).
STEP 3: Call get_invoice_status with the cleaned invoice_number.
STEP 4: Read the tool result carefully.
STEP 5: Compose a short, business-friendly response using ONLY data from the tool.

## YOUR TASK IS COMPLETE WHEN
You have called the tool, received a result, and delivered a response in the
required output format below. No further tool calls are needed after that.

## REQUIRED OUTPUT FORMAT
Always respond in this exact format. No extra text before or after.

📄 Invoice Status — {{invoice_number}}
──────────────────────────────────────
Supplier     : {{supplier_name}}
Amount       : {{currency}} {{invoice_amount}}
Invoice Date : {{invoice_date}}
Status       : {{status}}
Payment Due  : {{payment_due_date}}
GL Status    : {{gl_posting_status}}
──────────────────────────────────────
{{one_sentence_summary_or_next_action}}
2
Upload to OCI Object Storage
OCI Console → Object Storage → Create Bucket → Name: oic-agent-templates → Visibility: Private

Upload file → Browse to invoice_status_agent_prompt_v1.0.txt → Click Upload.

After upload, copy the Object URL. It looks like:
https://objectstorage.{region}.oraclecloud.com/n/{namespace}/b/oic-agent-templates/o/invoice_status_agent_prompt_v1.0.txt

✅ Verify: URL is accessible. File shows correct size. URL copied to clipboard.

🧠 Why each section of the Prompt Template matters

🧠 Identity section
Tells the LLM exactly what role it is playing. Without this, the model responds generically. With it, responses sound like a trained AP specialist, not a generic chatbot.
🚫 Hard Rules section
Prevents hallucination. RULE 1 and RULE 2 force the agent to always use the tool result — never invent data. This is the most important anti-hallucination mechanism in the entire agent.
✅ Completion signal
Without this, the agent doesn't know when to stop — it may call the tool again "to confirm" or add extra steps. The completion signal ensures it delivers one clean answer and stops.
📋 Output Format section
Guarantees consistent, parseable responses. If the agent response is consumed by another system (Teams bot, email, dashboard), the output format must be predictable every single time.

🔧 Section 6: Create the Tool — register the agent's capability

The Tool is what the Agent calls when it decides to act. In OIC Gen3, a Tool is a registered description + schema + endpoint. The LLM reads the description to decide when to call it.

💡 Remember: The description field is the most important field in the Tool. This is what the LLM reads to decide whether to call this tool. A vague description causes wrong tool selection. A precise description causes accurate, efficient execution every time.

📋 Step-by-step: register the Tool in OIC Gen3 AI Agent Studio

1
Navigate to AI Agent Studio → Tools
OIC Gen3 console → Left menu → AI Agent Studio → Click Tools tab → Click Create Tool.

✅ Verify: Tool creation form opens with Name, Description, Classification, Endpoint, and Parameters fields.
2
Fill in the Tool configuration
Enter these exact values:
"name":             "get_invoice_status",
"description":      "Retrieves the current status of an Oracle Fusion Accounts Payable invoice
 by invoice number. Returns: invoice status, supplier name, invoice amount,
 currency, invoice date, payment due date, and GL posting status. Use this
 tool whenever a user asks about invoice status, payment status, or whether
 an invoice has been approved or paid. Do NOT use for PO status — that is
 a different tool.",
"classification":   "READ",
"oicEndpoint":      "[PASTE YOUR OIC INTEGRATION REST URL HERE]",
"httpMethod":       "POST",
"timeout_seconds":  30,
"retry_on_failure": true,
"max_retries":      2
Replace [PASTE YOUR OIC INTEGRATION REST URL HERE] with the URL you copied in Section 4 Step 7.

Why READ classification? This tool only fetches data from Fusion. READ tools can be called by the agent autonomously without human approval.
3
Define the parameter schema
In the Parameters section, add one parameter:
Parameter Name : invoice_number
Type           : string
Required       : true
Description    : "The Oracle Fusion invoice number exactly as shown in the system,
                  e.g. INV100234. Always uppercase. No spaces."
Why the description on the parameter? The LLM reads parameter descriptions to understand how to extract the value from the user's message. "Always uppercase. No spaces." ensures INV 100 234 gets cleaned to INV100234 before the tool call.

Click Save Tool.

✅ Verify: Tool appears in the Tools list with name get_invoice_status and classification READ.
4
Test the Tool directly from Agent Studio
Click on get_invoice_status in the tools list → Click Test Tool → Enter test input:
{ "invoice_number": "INV100234" }
Click Run. The tool calls your OIC integration and shows the SUMMARY JSON response.

✅ Verify: Tool test returns the 8-field SUMMARY JSON. HTTP status 200. Response time under 5 seconds.

🤖 Section 7: Create the Agent — bring it all together

Now we create the Agent itself — the component that connects the Prompt Template, the Tool, the LLM, and the ReAct loop into one working AI system.

1
Navigate to AI Agent Studio → Agents → Create Agent
OIC Gen3 console → AI Agent Studio → Agents tab → Click Create Agent.

Enter: Name: InvoiceStatusAgent | Description: "Answers invoice status questions by calling Oracle Fusion ERP."

✅ Verify: Agent creation wizard opens with 5 configuration sections.
2
Configure LLM and runtime parameters
In the LLM Configuration section:
SettingValueClick / Select
LLM ProviderOCI Generative AISelect from dropdown
Modelcohere.command-r-plusSelect from dropdown
Agent PatternReActSelect from dropdown
max_iterations5Type in field
temperature0.1Type in field
max_tokens500Type in field
session_timeout (s)60Type in field
3
Link the Prompt Template
In the Prompt Template section → Select OCI Object Storage → Browse to bucket oic-agent-templates → Select invoice_status_agent_prompt_v1.0.txt → Click Select.

✅ Verify: Template URL appears in the Prompt Template field. Preview shows the first few lines of your template.
4
Assign the Tool
In the Tools section → Click Add Tool → Search for get_invoice_status → Select it → Click Add.

At runtime, the LLM receives the complete tool definition — name, description, and parameter schema — as part of the context. This is how it knows what the tool does and when to call it.

✅ Verify: Tool get_invoice_status appears in the agent's assigned tools list. Classification shows READ.
5
Configure security and save
In the Security section:
  • IAM Role: Select the OCI IAM role with READ access to the OIC integration endpoint
  • Enable audit logging: ON → Logging group: select your OCI Logging group
  • Memory: OFF (not needed for stateless invoice lookups)

Click Save Agent.

✅ Verify: Agent appears in the Agents list with status INACTIVE. All 5 sections show green checkmarks.

🔄 Section 8: End-to-end runtime execution — what happens when a user asks

Before testing, understand exactly what happens at runtime so you can diagnose issues intelligently. This is the complete millisecond-by-millisecond flow.

// RUNTIME EXECUTION TRACE — Invoice Status Agent
// User: "What is the status of invoice INV100234?"

[t+000ms] User message arrives at OIC Agent endpoint (REST POST)
[t+010ms] Agent session created. Session ID assigned. Audit log entry written.
[t+020ms] Prompt Template loaded from OCI Object Storage
[t+025ms] Template parameters injected: {{current_date}}, {{user_name}}
[t+030ms] Context assembled: [System Prompt] + [Tool Definitions] + [User Message]
[t+035ms] LLM CALL #1 (THINK): Sending context to OCI GenAI (Cohere R+)
[t+800ms] LLM responds: "I need invoice_number=INV100234. Calling get_invoice_status."
[t+810ms] TOOL CALL: get_invoice_status({invoice_number: "INV100234"})
[t+820ms] OIC Integration invoked: GET_INVOICE_STATUS
[t+900ms] Oracle Applications Adapter calls Fusion AP REST API
[t+1800ms] Fusion returns full invoice JSON (200+ fields)
[t+1810ms] OIC mapping trims to 8-field SUMMARY JSON
[t+1820ms] SUMMARY JSON returned to Tool layer
[t+1830ms] TOOL RESULT added to agent context as OBSERVATION
[t+1840ms] LLM CALL #2 (RESPOND): Context now includes tool result
[t+2600ms] LLM generates formatted business response in required output format
[t+2610ms] SESSION COMPLETE. Response returned to user. Audit log closed.
💡 Key insight for architects: The agent makes exactly 2 LLM calls for this use case — one THINK call and one RESPOND call. Total LLM latency is around 1.6 seconds. Total end-to-end is around 2.6 seconds. The Fusion API call is the slowest part at ~900ms. If your Fusion is slow, consider caching repeated queries on the same invoice within a time window.

🧪 Section 9: Testing with sample invoice inputs

Good testing covers happy paths, edge cases, and failure scenarios. Here are the exact tests to run in OIC Gen3 AI Agent Studio's test panel.

📋 Step: open the Agent Test Panel

OIC Gen3 → AI Agent Studio → Agents → Click on InvoiceStatusAgent → Click Test Agent tab → you will see a chat-like interface. Enter your test messages and click Send.

🧪 Test Case 1 — standard invoice query (happy path)

Input:
"What is the status of invoice INV100234?"
Expected agent response:
📄 Invoice Status — INV100234
──────────────────────────────────────
Supplier     : Acme Supplies Ltd
Amount       : INR 1,24,500
Invoice Date : 05-Jun-2026
Status       : Approved
Payment Due  : 20-Jun-2026
GL Status    : Posted
──────────────────────────────────────
This invoice is approved and payment is scheduled for 20-Jun-2026. No action required.
✅ Pass if: format is exact. No invented data. Exactly matches Fusion ERP record.

🧪 Test Case 2 — informal invoice number (input cleaning)

Input:
"Can you check inv 100234 for me?"
Agent cleans "inv 100234" → "INV100234" → calls tool → returns same result as Test 1. Prompt Template RULE 3 handles this cleaning.

✅ Pass if: agent returns correct invoice data despite informal input format.

🧪 Test Case 3 — invoice not found

Input:
"What is the status of invoice INV999999?"
Expected agent response:
📄 Invoice Status — INV999999
──────────────────────────────────────
Invoice INV999999 was not found in Oracle Fusion ERP.
Please verify the invoice number and try again.
──────────────────────────────────────
✅ Pass if: agent says NOT FOUND. Does NOT invent an invoice. Does NOT guess the status.

🧪 Test Case 4 — out of scope question (guardrail test)

Input:
"What is John's salary in the payroll system?"
Agent declines politely: "I am InvoiceBot and can only help with Accounts Payable invoice status. For payroll queries, please contact the HR team or use the Payroll portal."

✅ Pass if: agent declines without calling any tool. No Fusion query is made. Scope restriction enforced.

🧪 Test Case 5 — multiple invoice numbers in one message

Input:
"Can you check both INV100234 and INV100567?"
Agent calls get_invoice_status twice — once for INV100234, once for INV100567 — and returns two formatted status blocks. This is the ReAct loop running 2 iterations (each with THINK → ACT → OBSERVE → RESPOND).

✅ Pass if: both invoices returned accurately. Total iterations ≤ 4. No hallucination between the two results.

⚠️ Section 10: Error handling and edge cases

🔴 Fusion API down (HTTP 503)
What happens: OIC integration receives 503. Fault handler triggers. Returns: status: "SERVICE_UNAVAILABLE"
Agent behaviour: "Oracle Fusion ERP is temporarily unavailable. Please try again in a few minutes."
Your action: Fault handler built in Section 4 Step 6. Tool retry (max 2) handles transient errors.
🟡 max_iterations reached
Symptom: Agent keeps calling the tool because it doesn't recognise the completion signal.
Root cause: Prompt template missing "YOUR TASK IS COMPLETE WHEN" clause, or output format not being followed.
Fix: Review the prompt template. Confirm completion signal is explicit. Re-upload. Re-test.
🟣 Agent invents invoice data
Symptom: Agent returns invoice data that doesn't match Fusion ERP.
Root cause: temperature too high, or RULE 1 + RULE 2 missing from prompt template.
Fix: Set temperature=0.1. Verify HARD RULES section is in the template. Re-upload. Re-test with a known invoice.
🔵 Tool returns no data (empty array)
Symptom: Fusion query returns items:[] because the invoice number format doesn't match Fusion's stored format.
Root cause: Fusion stores "00100234" but user typed "INV100234".
Fix: Add a normalisation step in the OIC integration request mapper. Strip "INV" prefix and left-pad with zeros if needed.

🔍 How to read agent logs for debugging

// In OCI Logging → Log Group for your agent → Filter by session_id

[THINK]   LLM input tokens: 847 | Output: "Calling get_invoice_status(INV100234)"
[ACT]     Tool: get_invoice_status | Input: {invoice_number: "INV100234"}
[ACT]     OIC Integration: GET_INVOICE_STATUS | HTTP: 200 | Latency: 923ms
[OBSERVE] Tool returned 8-field SUMMARY JSON
[THINK]   LLM input tokens: 1124 | Output: Formatted response in required format
[DONE]    Session complete | Total iterations: 2 | Total tokens: 1971 | Time: 2.4s

// If you see [THINK] called 5 times without [DONE] = completion signal issue
// If [ACT] shows HTTP 500 = OIC integration or Fusion connectivity issue
// If [OBSERVE] shows empty items[] = invoice number format mismatch in Fusion

🚀 Section 11: Deployment steps — from build to active

Your agent is built and tested in the development environment. Now deploy it so it can receive real requests.

💡 What does "deploy" mean for an agent? Deploying means activating it and publishing its REST endpoint so external systems can invoke it. Until deployed, the agent exists only in the Studio and cannot be called by anyone outside your OIC instance.
Step 1 — Pre-deployment check in DEV
Confirm all 5 test cases pass. Confirm the OIC integration GET_INVOICE_STATUS is Active. Confirm the Prompt Template is uploaded and readable. Confirm the Tool test returns real data. Confirm OCI Logging is configured. Only proceed if all pass.
Step 2 — Activate the Agent
AI Agent Studio → Agents → InvoiceStatusAgent → Click Activate → Confirm Tracing Level: Audit (leave ON for first 2 weeks in production, then switch to Production to reduce log volume) → Click Activate. Status changes from INACTIVE to ACTIVE.
Step 3 — Copy the Agent Endpoint URL
After activation → Click Endpoint Details → Copy the REST endpoint URL: https://your-oic-instance.integration.ocp.oraclecloud.com/ic/api/ai-agent/v1/agents/InvoiceStatusAgent/invoke. This is the URL your users and applications call.
Step 4 — Run a post-deployment smoke test
Using Postman or any REST client, POST to the agent endpoint with basic auth. Body: {"message": "What is the status of invoice INV100234?"} Confirm you get the formatted invoice response. If this works, your deployment is successful.
Step 5 — Set up OCI Monitoring Dashboard
OCI Monitoring → Create Dashboard → Add these metrics: agent invocations per hour, average session duration, total LLM tokens per day, tool error rate, session timeout count. This is your production health monitor. Review daily for the first week.

🔁 Section 12: Migration from lower to higher environment (DEV → TEST → PROD)

Enterprise deployments always follow a promotion pipeline. The OIC Gen3 agent system has multiple components that must be migrated together — in the right order.

📦 What needs to be migrated

📝
Prompt Template
Upload same file to TARGET env OCI Object Storage bucket
⚙️
OIC Integration
Export IAR from DEV. Import and activate in TARGET env.
🔧
Tool Definition
Re-register Tool in TARGET env with TARGET integration URL.
🤖
Agent Configuration
Re-create Agent in TARGET env with TARGET env parameter values.
🔐
OCI Vault Secrets
Create/verify secrets in TARGET OCI Vault before migration.

📋 Migration steps — DEV to TEST (repeat for TEST to PROD)

Migration Step 1 — Prepare target environment secrets
In TEST OCI Vault: create secrets for TEST Fusion OAuth client_id and client_secret. Create secret for TEST Fusion hostname. These will be different values from DEV. The OIC integration in TEST will point to TEST Fusion, not DEV Fusion.
Migration Step 2 — Export OIC Integration from DEV
OIC DEV Console → Integrations → GET_INVOICE_STATUS → Actions (⋮) → Export IAR → Save the .iar file. This file contains the complete integration definition.
Migration Step 3 — Import and configure in TEST
OIC TEST Console → Integrations → Import → Upload the .iar file → Update the Fusion Connection to point to TEST Fusion hostname → Update OCI Vault references to TEST vault secrets → Validate all mappings → Activate with Audit tracing.
Migration Step 4 — Upload Prompt Template to TEST Object Storage
TEST OCI Object Storage → Create bucket oic-agent-templates → Upload the same invoice_status_agent_prompt_v1.0.txt file → Copy the TEST object URL (different from DEV URL).
Migration Step 5 — Register Tool in TEST Agent Studio
OIC TEST Console → AI Agent Studio → Tools → Create Tool → Use same tool definition as DEV but change the oicEndpoint to the TEST OIC integration REST URL → Save and test from test panel using a TEST Fusion invoice number.
Migration Step 6 — Create Agent in TEST
OIC TEST Console → AI Agent Studio → Agents → Create Agent → Same configuration as DEV but: Prompt Template URL = TEST Object Storage URL, Tool = TEST env tool, IAM Role = TEST env role → Save → Activate → Run all 5 test cases against TEST Fusion invoices → Confirm 100% pass rate.
Migration Step 7 — Sign-off and document
Get UAT sign-off on TEST environment results. Document all TEST env URLs and configurations. Repeat steps 1–6 for PROD when UAT is approved. PROD uses lower tracing level (Production, not Audit) and higher rate limits.
Configuration item DEV value TEST value PROD value
Fusion Hostnamefusion-dev.example.comfusion-test.example.comfusion.example.com
OCI Vault (Secrets)vault-devvault-testvault-prod
OIC Tracing LevelAuditAuditProduction
OCI Object Storage Bucketoic-agent-templates-devoic-agent-templates-testoic-agent-templates-prod
Agent max_iterations555

✅ Section 13: Production readiness checklist

Before declaring your Invoice Status Agent production-ready, complete every item on this checklist. Each item represents a real risk if skipped.

🔧 Integration & Tool
  • ☐ GET_INVOICE_STATUS integration is Active in PROD
  • ☐ Integration uses PROD Fusion credentials (not DEV)
  • ☐ Credentials stored in PROD OCI Vault (not hardcoded)
  • ☐ Response mapping returns SUMMARY only (8 fields)
  • ☐ Fault handler returns structured JSON on error
  • ☐ Tool timeout set to 30 seconds
  • ☐ Tool retry configured (max 2)
  • ☐ Tool tested with 5 real PROD invoice numbers
📝 Prompt Template
  • ☐ Template uploaded to PROD OCI Object Storage
  • ☐ HARD RULES section includes RULE 1 and RULE 2
  • ☐ Completion signal "YOUR TASK IS COMPLETE WHEN" present
  • ☐ Output format matches business requirements
  • ☐ Template tested for out-of-scope rejection
  • ☐ Template version documented (v1.0)
🤖 Agent configuration
  • ☐ Agent is Active in PROD
  • ☐ LLM = OCI Generative AI (PROD endpoint)
  • ☐ temperature = 0.1
  • ☐ max_iterations = 5
  • ☐ session_timeout = 60s
  • ☐ memory_enabled = false
  • ☐ OCI IAM role correctly scoped
  • ☐ Audit logging connected to PROD log group
🛡️ Security & Compliance
  • ☐ No credentials hardcoded in any OIC flow
  • ☐ Fusion OAuth token managed by OCI Vault
  • ☐ Agent endpoint secured (OIC credentials required)
  • ☐ Prompt injection test passed (Test Case 4)
  • ☐ Agent only accesses AP — not HR, GL, or Payroll
  • ☐ OCI Audit logging confirmed active
📊 Observability
  • ☐ OCI Monitoring dashboard created
  • ☐ Alert on tool error rate > 5% configured
  • ☐ Alert on session timeout count > 3/hour configured
  • ☐ Token usage baseline established from TEST
  • ☐ Monthly OCI GenAI cost estimate documented
  • ☐ On-call runbook written for agent failures
🚦 Go-Live gates
  • ☐ All 5 test cases pass in PROD environment
  • ☐ UAT sign-off received from Finance team
  • ☐ IT Security sign-off on agent security controls
  • ☐ Rollback plan documented
  • ☐ Support team trained on how to monitor agent
  • ☐ Agent endpoint URL shared with consuming applications

🚨 Section 14: Common mistakes and fixes


🎯 Section 15: Key takeaways — what you have built

You have just completed a full end-to-end build of a production-grade OIC Gen3 AI Agent. Here is a precise summary of what you built, learned, and can now do.

⚙️ OIC Integration (Layer 4)
  • REST-triggered integration GET_INVOICE_STATUS
  • Calls Oracle Fusion AP REST API via Oracle Applications Adapter
  • Maps Fusion response to 8-field SUMMARY JSON
  • Includes fault handler for structured error responses
  • Credentials managed by OCI Vault
🔧 Tool (Layer 3)
  • Tool: get_invoice_status
  • Classification: READ (autonomous — no human approval)
  • Parameter: invoice_number (string, required)
  • Full Golden Rule description enabling accurate LLM tool selection
  • Timeout 30s, retry 2x on failure
📝 Prompt Template (Layer 2)
  • 7-section template: Identity, Mandate, Hard Rules, Reasoning, Completion, Output Format
  • RULE 1+2 enforce anti-hallucination (always use tool data)
  • RULE 3 handles invoice number cleaning
  • Stored in OCI Object Storage — not hardcoded
  • Versioned: v1.0
🤖 Agent (Layer 1)
  • InvoiceStatusAgent — ReAct pattern
  • LLM: OCI GenAI Cohere Command R+
  • temperature=0.1, max_iterations=5, timeout=60s
  • Deployed and active. REST endpoint available.
  • OCI Audit logging connected
🧠 The 5 mental models you now own
Build bottom-up, test at every layer: Integration → Tool → Prompt Template → Agent. Never skip a layer. Each layer depends on the one below being tested and reliable.
The Tool description is the agent's decision logic: the LLM reads it on every THINK step. Precise descriptions = correct tool selection. Vague descriptions = wrong tool calls.
SUMMARY payloads prevent context window bloat: 8 fields vs 200 fields is a 25× token reduction. Cost, latency, and response quality all improve with SUMMARY responses.
Anti-hallucination lives in the Hard Rules section: RULE 1 and RULE 2 in the prompt template are the primary defence against invented data. temperature=0.1 is the secondary defence.
Migration = rebuild with environment-specific values: nothing is "moved" between environments. Everything is rebuilt with different connection strings, vault secrets, and object storage URLs. Only the prompt template text file and the IAR export are identical.
🌱 What you can build next with what you know now:

You have completed the complete lifecycle of an OIC Gen3 AI Agent — build, test, deploy, and migrate. The same pattern applies to every enterprise AI agent you will ever build on this platform.

Change the integration to HCM and the tool to get_leave_balance → you have an HR Self-Service Agent.
Change the integration to SCM and the tool to get_po_status → you have a Procurement Agent.
Add a second tool flag_invoice_for_review → the same agent can now take action, not just answer.

The Invoice Status Agent is not the destination. It is the foundation. Everything you build from here starts from what you learned in this lab.

Build Precisely. Test Thoroughly. Deploy Confidently.

Comments