22 AI Agents
This chapter provides information on creating, testing, deploying and monitoring agents in your workspace.
Agents are end-to-end agentic applications. Agents are defined through a graph of steps represented by nodes of different types (triggers, agents, guardrails, or tools). Agents can be defined through a no-code visual flow builder and through code via third-party libraries, such as LangGraph.
- Custom Tool: The Custom Code tool lets agent developers extend AI Data Platform with their own Python code. You package your tool implementation as a ZIP file, upload it to your workspace, and configure it. The agent calls your code as a tool, with parameters supplied by the LLM at runtime.
- HTTP: The HTTP Request tool lets your agent call any HTTPS REST API. You configure the request, including method, URL, headers, query parameters, request body, authentication, and optionally, a response optimization step. The agent then invokes the endpoint at runtime. The HTTP request tool is available in both the visual builder and the code builder. In the code builder, the tool is configured through the aidpUtils Python library.
- Prompt: The prompt tool allows the AI developer to define a parametrized prompt that can be issued to an LLM for their choice. Common use cases for a prompt tool include email drafting tasks, translation tasks, style conversion, git commit message, and code explanations.
- Remote MCP Server: Agent developers can connect their agents to remote model context protocol (MCP) servers using the Remote MCP Server tool.
- RAG: The RAG tool lets agents pull relevant external knowledge before generating a response. In AI Data Platform Workbench, the RAG tool queries a knowledge base (23ai Vector Search) and retrieves semantically relevant document chunks. Those chunks are then passed to the agent for response generation.
- SQL: The SQL tool enables agents to execute SQL queries against structured data sources registered via external catalogs, such as Oracle Autonomous AI Lakehouse, Oracle Autonomous AI Transaction Processing, or Oracle AI Database. The tool is intended for scenarios where the SQL queries are predefined and can be parametrized. The objective is to let an agent assign values to the parameters. This tool is not an NL2SQL tool that generates a SQL query based on a natural language prompt.
Note:
The SQL tool only performs queries against data in an external catalog. It does not support data stored in a standard catalog.
Note:
You must attach an AI Compute to your agent before you can test a system tool. If no compute is attached, the Test tab is disabled.Creating agents in AI Data Platform Workbench generates an agent artifact file (.aflow) in the workspace folder that you select. This file can’t be modified.
Multi-agent Systems and Supervisor Patterns
A multi-agent system is an AI application design in which a user request is handled by multiple cooperating agents instead of one large, all-purpose agent.
Each agent has its own role, instructions, model configuration, memory policy, and allowed tools. The flow defines how the request moves between those agents and how the final answer is produced.
This design is useful when a workflow naturally separates into specialist responsibilities. For example, one agent can retrieve data, another can call an API, another can summarize findings, and a supervisor can decide which specialist to use and combine the results into a single response.
Note:
As a design principle, it's best to start with the smallest agent design that meets the requirements. Add multiple agents when separation of concerns improves reliability, security, maintainability, or observability more than it increases cost and complexity.Benefits of Multi-agent Systems
- Specialization: give each agent a focused job, prompt, and tool set instead of one crowded instruction block.
- Routing and decomposition: let a supervisor interpret the request, split it into subtasks, and choose the right specialist for each subtask.
- Tool and data isolation: expose sensitive or high-impact tools only to the agents that are responsible for using them.
- Governance and troubleshooting: make handoffs, tool ownership, memory settings, and failure points easier to inspect.
When to Choose Multi-Agent or Single Agent Designs
A single agent with more tools is often the right first design. It is simpler to test, cheaper to run, and easier to reason about when the task has one clear objective and one permission model. Use a multi-agent design when the workflow benefits from explicit roles, bounded tool access, or a supervisor that can coordinate multiple specialist outputs.
| Design Question | Use single agents when... | Use multi-agents when... |
|---|---|---|
| Task shape | The request has one main objective and one response stile. | The request must be decomposed, routed, verified, or synthesized across specialties. |
| Tools and data | The same instruction set and permission model can safely govern all tools | Different agents need different tools, data sources, or access boundaries. |
| Instructions | The prompt remains clear even with all business rules and tool guidance in one place. | Instructions are easier to maintain as smaller, role-specific prompts. |
| Cost and latency | You want the shortest path from user message to answer. | The reliability, governance, or maintainability benefits justify extra orchestration. |
| Troubleshooting | Failures are simple to debug in one trace. | You need explicit handoffs, state isolation, and clearer ownership for each step. |
Supported Pattern: Orchestrator/Supervisor
The current canvas experience supports the orchestrator / supervisor pattern. In this pattern, the Chat Trigger receives the user message, optional Guardrails evaluate the input, and a Supervisor Agent acts as the orchestrator for the rest of the flow.
The supervisor should focus on planning, routing, delegation, and final response synthesis. It decides which executor agent should handle a task, sends that executor a scoped instruction, reviews the result, and then either delegates another step or returns the final response. Executor agents should be narrower specialists: they do the assigned work, use their attached tools, and return useful results to the supervisor.
About the Visual Flow Canvas
An agent is assembled by dragging nodes and tool templates from the left palette onto the canvas, then connecting the nodes in the order the request should travel.
Selecting a node opens a configuration panel at the bottom of the screen.

| Canvas Element | Purpose |
|---|---|
| Chat Trigger | Entry point for a user message. In the screenshot this node is labeled Message and typically sits at the top of the flow.
A chat trigger node can be connected to an agent, a supervisor agent, or a guardrails node. Only one chat trigger is allowed per canvas. |
| Guardrails | Optional policy and safety layer placed before or after model work. The guardrails policies include PII, content moderation, and prompt injection detection.
A guardrails node can filter traffic between a chat trigger and an agent node, between a supervisor and executor agents, or between agent and tool nodes. We recommend a single guardrails node between the chat trigger and the agent node. |
| Supervisor Agent | The orchestrator. It receives the user request, decides which executor agent or tool should handle each task, and coordinates the final answer.
Only one supervisor agent is allowed in a canvas. |
| Agent | An executor agent. Each executor should have a clear specialty, such as data retrieval, API lookup, summarization, or document question answering.
Use an agent / executor agent for a single agent system. |
| Tool templates | Reusable capabilities that can be attached to individual executor or supervisor agent. Tool templates include SQL, RAG, Prompt, HTTP, Remote MCP server, and Custom Tool. |
| Development / Playground | Mode selector above the canvas. Development is used while editing the agentic system; Playground is used to initiate test sessions and inspect agent behavior.
Playground requires that an AI compute is attached to your agent. |
| Zoom control | Canvas zoom selector. The screenshots show 60 percent and 90 percent zoom levels. |
Add Chat Trigger and Agent to Visual Builder Canvas
Your first step after creating an agent with the Visual Builder should be to add a chat trigger and a supervisor agent.

Configure a Supervisor Agent
You need to configure a supervisor agent added to your Visual Builder canvas with instructions outlining the supervisor role.

| Field | Configuration |
|---|---|
| Agent Name | Provide a descriptive name for your supervisor agent. A good, descriptive name will be beneficial when debugging the system behavior through traces and logs. |
| Agent Description | Provide a description of the agent purpose, role, and general behavior. Useful for documentation purposes. |
| Region | Choose the region where the OCI Generative AI model used by Supervisor Agent is hosted. See Generative AI Models by Region. |
| Model | Choose the OCI Generative AI service model used by the supervisor. The dropdown lists the models available in the region you selected. |
| Agent instructions | Describe the supervisor role, routing rules, delegation policy, tool-use expectations, and final response format. |
- Navigate to the agent in your workspace.
- Click the Supervisor Agent node on your canvas.
- Provide a meaingful name and description for your supervisor agent.
- Enter the region and model for the OCI Generative AI service model used by the supervisor.
- Provide the agent instructions for your Supervisor Agent.
Suggested Supervisor Instructions
You should use the Instructions field for a Supervisor Agent to make the supervisor responsible for orchestration, not for doing every task itself.
Keep the instructions concrete so routing decisions are predictable. See the following for an example of a set of Supervisor instructions:
You are the supervisor for a multi-agent system.
Responsibilities:
- Understand the user's request and break it into subtasks.
- Select the most appropriate executor agent or tool for each subtask.
- Do not perform specialist work yourself when an executor agent is available.
- Ask for clarification only when required information is missing.
- Combine executor outputs into a concise final answer.
- Mention important assumptions, limits, or failed tool calls in the final answer.
Routing rules:
- Use the SQL agent for structured data questions.
- Use the HTTP agent/tool for external API lookups.
- Use the RAG agent/tool for document or knowledge-base questions.
- Use the prompt tool for reusable prompt-only transformations.Configure Supervisor Agent Memory and State Isolation
The Memory tab for a Supervisor Agent controls how much conversation and tool-output history is available to the supervisor and how much context is shared with executor agents.

| Field | Configuration |
|---|---|
| Enable Agent Memory | Enable when users need multi-turn continuity. Disable for isolated, one use tasks.
This field cannot be disabled for Supervisor Agents. |
| Limit conversation history | Enable to truncate the LLM context window after the specified limit is hit. Disable to show the full history. |
| Truncation configuration | If Limit conversation history is enabled, use this field to set the conditions for truncating the the context window.
Options are:
|
| Maximum Message Limits and Token Budget | One or both of these options is displayed, depending on your choice for Truncation Configuration.
Default values are 20 messages and 5000 tokens. We recommend starting with moderate values and adjusting as needed. |
| State Isolation for Executor Agents | Select Stateless, Private, or Shared.
|
- Navigate to the agent in your workspace.
- Click the Supervisor Agent node on your canvas.
- Click the Memory tab.
- Choose whether to enable Limit conversation history. Select a Truncation Configuration and set limits, if enabled.
- Choose an option for State Isolation for Executor Agents.
Models Parameter Tab
The model parameters tab lets you configure model-specific parameters that are available for the selected model.
Model parameters can be configured separately for supervisor and executor agents. Parameters you can use include temperature, top K, top P, and frequency penalty.
Note:
Only a subset of models exposes configurable parameters. Furthermore, the parameters vary across model families.
Add Guardrails to an Agent
You can add additional layers of protection to your agents by adding one or more guardrail nodes to your canvas.
| Guardrail | Options | When to Use |
|---|---|---|
| Personal identifiable information (PII) |
|
Use when the flow must block or mask sensitive personal data before or after model processing. |
| Content moderation prevention | Input and Output rows with Block, Inform, and Allow options. | Use to define how the flow handles hate, sexual, violent, toxic, derogatory, or harassing content. |
| Prompt Injection detection | Input row with Block and Allow options. | Use to reduce the chance that malicious instructions override the system or agent instructions. |
Add Executor Agents and Tools to an Agent
You can add executor agents to tools to perform specialized work for the supervisor agent.

- Navigate to the agent in your workspace.
- Drag an Agent node from the palette to your canvas. Agent nodes should be placed below a Supervior Agent.
- Drag Tools from the palette to your canvas.
- Click and drag the connector handle on your Supervisor Agent to connect to the Agent nodes.
- Click and drag the connector handle on your Agents to connect to the Tool nodes.
Executor Agent Configuration
Agent nodes can be configured by modifying settings on their Configuration, Memory, and Model tabs to help you define the purpose of each agent.
Agents should be configured narrowly, given a specific function and goal, so the supervisor agent can route work reliably.
Table 22-1 Agent Configuration Tab
| Field | Configuration |
|---|---|
| Agent Name | Best practice is to name each executor agent according to its specialty, such as SQL_AGENT, DOCUMENT_AGENT, API_AGENT, or SUMMARY_AGENT.
The name of each executor agent is visible to the supervisor agent, so use descriptive names. |
| Agent Description | Provide a detailed description of each executor agent. The description of each executor agent is visible to the supervisor agent. |
| Region | Choose the region where the OCI Generative AI model used by the Agent is hosted. See Generative AI Models by Region. |
| Model | Choose the OCI Generative AI service model used by the agent. The drop-down menu lists the models available in the region you selected.
Select a model that fits the executor task. Executor agents don't need to use the same model as the supervisor agent. |
| Agent instructions | Describe exactly what the executor should do, what tools it may use, and what output structure it should return. |
Executor Agent Memory Tab
In the case of executor agents connected to a supervisor agent, the memory for executors is configured in the supervisor node and applied to all executor agents.
| Field | Configuration |
|---|---|
| Enable Agent Memory | Enable when users need multi-turn continuity. Disable for isolated, one use tasks. |
| Limit conversation history | Enable to truncate the LLM context window after the specified limit is hit. Disable to show the full history. |
| Truncation configuration | If Limit conversation history is enabled, use this field to set the conditions for truncating the the context window.
Options are:
|
| Maximum Message Limits and Token Budget | One or both of these options is displayed, depending on your choice for Truncation Configuration.
Default values are 20 messages and 5000 tokens. We recommend starting with moderate values and adjusting as needed. |
| State Isolation for Executor Agents | Select Stateless, Private, or Shared.
|
Executor Agent Model Parameters Tab
The model parameters tab lets you configure model-specific parameters that are available for the selected model.
Note:
Only a subset of models exposes configurable parameters. Parameters also vary across model families.Examples of parameters include temperature, top K, top P, and frequency penalty. Model parameters can be configured separately for supervisor and executor agents.
Suggested Executor Instructions
You are the SQL executor agent.
Responsibilities:
- Translate the supervisor's task into safe SQL tool usage.
- Use only the SQL tools attached to this agent.
- Return a concise answer plus any important query assumptions.
- Do not invent data. If the tool cannot answer, say what is missing.
- Return structured output with: answer, evidence, assumptions, and follow_up_needed.
Checklist for Agents through Visual Builder
Use this list as a guide to ensure you've included and configured every necessary component for an agent built using the Visual Builder.
Build Checklist
- The agent has exactly one expected entry point: Chat Trigger / Message.
- Guardrails are connected in the intended position and enabled where required. We recommend inserting guardrails between the trigger message and the agent.
- The Supervisor Agent has a selected region, selected model, and orchestration instructions. Same for executor agents.
- Configure memory of the multi-agent system in the Memory tab of the Supervisor agent. Select executor state isolation that matches the privacy and continuity requirements.
- Each executor Agent has a clear specialty and narrow instructions.
- Each tool is attached only to the agent that should use it.
- No node is disconnected.
- An AI compute is attached to the agentic system to test individual tools and for running the Playground experience.
Table 22-2 Common Issues
| Issue | Likely Cause | Suggested Action |
|---|---|---|
| Supervisor does not call an executor | Supervisor instructions are too vague or no executor is connected. | Add explicit routing rules and confirm the executor node is connected to the supervisor. |
| Executor returns broad or off-topic answers | Executor instructions are too general. | Make the executor role narrower and define the required output structure. |
| Tool is not used | Tool is disconnected or attached to the wrong agent. | Check the tool connection and the agent tool count badge. |
| Guardrail does not fire | Guardrail section is configured but not enabled. | Open the guadrails node and confirm the section toggle is on. |
| Context leaks across agents | State isolation is set to Shared or memory is broader than intended. | Use Stateless or Private isolation for stricter separation. |
| Follow-up questions lose context | Memory is disabled or truncation is too aggressive. | Enable memory and adjust the maximum message limit. |
Agent Flows Through Code
You can bring your own LangGraph code base to AI agents in Oracle AI Data Platform Workbench or create a brand new LangGraph agent directly on the platform through the agent coding experience.
You can use the AI Data Platform Workbench utility Python library aidputils to configure your foundational model and import system tools to your agent. For aidputils API reference, see Aidp-utils API for Oracle AI Data Platform Workbench.

You create an agent through code by either uploading an existing code file or creating code files directly in your agent through the inline editor.
- Python (.py)
- JSON
- TXT
- CSV
- PSV
- SH
- Folder
You can see and navigate through the available code files by clicking the file selector drop-down list.

Entry and Dependency Files
Entry files are code files that have the class with setup and invoke methods expected for an agent defined as code. Oracle AI Data Platform Workbench requires you to set an entry file for agents through code.
Dependency files are files that include third-party libraries required by your agent defined as code. Dependency files are typically requirements.txt files that contain a list of the required third-party libraries.
Note:
Third-party libraries are installed when you test your code in the editor by clicking the Play button or when you test the agent through the Test tab. We recommend install third-party libraries by testing the code first. Errors during installation of the libraries are displayed in the output cell.Agent Class
AgentBasic is a template class for setting up and invoking a simple conversational agent using a stateful LangGraph workflow. It demonstrates the structure required for minimal agent development with two main methods:
setup(): Initializes the agent workflow and defines the graph.invoke(user_query, **kwargs): Runs the agent on a user message and returns the response.
It can be directly run and tested using a main() function before integration into a larger system.
Definition
class AgentBasic:
def __init__(self) -> None:
self.graph = None
def setup(self) -> None:
self.graph = StateGraph(MessagesState)
self.graph.add_node(mock_llm)
self.graph.add_edge(START, "mock_llm")
self.graph.add_edge("mock_llm", END)
self.graph = self.graph.compile()
system_prompt = "Be a helpful assistant."
async def invoke(self, user_query: str, **kwargs):
user_message = HumanMessage(content=user_query)
messages = {"messages": [dict(user_message)]}
try:
return self.graph.invoke(messages)
except Exception as e:
import traceback
logger.error(f"Exception while calling invoke {e}", exc_info=True)
print("Stack trace:\n", traceback.format_exc())
Test Invocation
This test invocation is ideal for initial functional testing.
Note:
Include a main entry point for stand-alone testing.import asyncio
async def main():
test_agent = AgentBasic()
test_agent.setup()
result = await test_agent.invoke("Hi there")
print("Agent response:", result)
if __name__ == "__main__":
asyncio.run(main())
- The script creates an agent, sets it up, and sends a sample user message.
- The agent responds ({"messages": [{"role": "ai", "content": "hello world"}]} in this example).
Usage Guide
Create an Agent class with the setup and invoke methods.
| setup() | Initializes the agent workflow | agent.setup() |
| invoke() | Runs the agent with a user message | await agent.invoke("Your question") |
- Asynchronous:
invoke()is an async method; use it withawaitor run in an async loop. - Testing: The included
main()guard (if __name__ == "__main__":) makes it easy to test the agent before deployment.
Build an Agent Through Code by Upload
You can build your end-to-end agent application with existing code by uploading your LangGraph code base.
Note:
You can upload individual files and folders up to a maximum of 500 files, each file can have a maximum size of size of 500MB. The upload is limited to a total size of 5GB.Build an Agent Through Code by Creating New Code
You can build your end-to-end agent application with existing code by creating code directly in your agent through the code editor.
- Python (.py)
- JSON
- TXT
- CSV
- PSV
- SH
- Folders
Set an Entry File for Agents through Code
Your AI agent through code requires an entry file that has the required class, setup, and invoke methods expected for your agent.
Set a Dependency File for Agents through Code
You need to set a dependency file for agents flows through code that contains any third-party libraries your code is dependent on.
Test Agent Code
You can test the code used for your agent from the Test tab to validate and debug code.
Agent Skills in Coding Experience
Agent Skills let an agent discover and use task-specific instructions, reference files, templates, assets, and optional executable scripts without hardcoding that domain knowledge into the agent’s instructions.
A skill is stored as a folder in your agent code base. Each skill has a required SKILL.md file that describes what the skill does and how the agent should use it. A skill can also include supporting files such as schemas, examples, prompts, templates, assets, or scripts.
For more information, see Agent Skills Overview.
- The agent discovers that a skill exists.
- The agent activates the skill only when it is relevant.
- The agent loads additional files from the skill folder only when needed.
- The agent may run an explicitly declared skill entrypoint, if the skill allows it.
When to use Agent Skills
- Domain-specific instructions
- Coding or data analysis workflows
- SQL generation guidance
- Business process playbooks
- File templates
- Schema references
- Reusable scripts for safe calculations, transformations, or lookups
How Skills Work at Runtime
At runtime, the host application determines which skill directories are available, such as project-level and user-level skill folders. The platform loads each skill’s metadata from SKILL.md and builds a catalog keyed by skill name.
The agent can then use skill-related tools:
| Tool | Purpose |
|---|---|
activate_skill(name) |
Loads the skill instructions from SKILL.md. |
list_skill_files(name, path) |
Lists files available inside a skill folder. |
load_skill_file(name, path) |
Loads a supporting file from the skill folder. |
run_skill_entrypoint(name, entrypoint, args_json, timeout_seconds) |
Runs an explicitly declared Python entrypoint, if allowed by the skill. |
Some environments may also embed a summary of available skills directly into the system prompt. In that setup, the agent can discover available skills from the prompt, then use activate_skill when it needs the full instructions.
Skill Folder Structure
A skill uses an Agent Skills-style folder layout:
<skills_dir>/
some-skill/
SKILL.md
references/
...
scripts/
...
assets/
...Only SKILL.md is required. The other folders are optional.
| Folder or File | Required | Purpose |
|---|---|---|
SKILL.md |
Yes | Main skill metadata and instructions. |
references/ |
No | Supporting documentation, schemas, examples, or templates. |
scripts/ |
No | Python scripts that may be run only when explicitly declared as entrypoints. |
assets/ |
No | Static assets used by the skill. |
Writing SKILL.md
Each skill must include YAML frontmatter at the top of SKILL.md, followed by Markdown instructions.
Basic Example
---
name: sql-helper
description: Helps the agent write safe SQL queries using project schemas.
license: internal
compatibility: "agent-platform"
metadata:
owner: data-platform
domain: analytics
allowed-tools: "analyzeQuery inspectSchema"
---
# SQL Helper
Use this skill when the user asks for SQL generation, query review, or schema-aware analysis.
Before writing SQL:
1. Inspect the relevant schema files in `references/`.
2. Prefer explicit column names.
3. Avoid destructive statements unless the user explicitly asks for them and the environment allows them.
Table 22-3 Supported Frontmatter Fields
| Field | Required | Description |
|---|---|---|
| name | Yes | Unique skill name used by the catalog and tools. |
| description | Yes | Short description used for discovery and routing. |
| license | No | License or usage policy for the skill. |
| compatibility | No | Compatibility note for supported runtimes or platforms. |
| metadata | No | String-to-string metadata map. |
| allowed-tools | No | Space-separated list of tools this skill permits. |
| entrypoints | No | List of executable entrypoints declared by the skill. |
Adding Supporting Files
Supporting files let a skill keep detailed content outside the main instructions. This keeps SKILL.md focused while still giving the agent access to richer context. For example:
skills/
sql-helper/
SKILL.md
references/
warehouse_schema.md
query_style_guide.md
examples.md
The agent can inspect these files with:
list_skill_files("sql-helper", "references")
load_skill_file("sql-helper", "references/warehouse_schema.md")
- Database schemas
- API examples
- Prompt templates
- Style guides
- Domain glossaries
- Step-by-step playbooks
- Test cases or examples
Creating an Executable Skill
A skill can optionally expose reusable executable behavior through run_skill_entrypoint. This is intended for controlled operations such as calculations, transformations, validation, or fetching structured data.
- The skill must include
run_skill_entrypointin allowed-tools. - The script must be explicitly declared in the entrypoints section of
SKILL.md.
Example Executable Skill
skills/
statistics-helper/
SKILL.md
scripts/
summarize_numbers.py
SKILL.md
---
name: statistics-helper
description: Computes basic summary statistics for numeric data.
allowed-tools: "load_skill_file list_skill_files run_skill_entrypoint"
entrypoints:
- name: summarize_numbers
script: scripts/summarize_numbers.py
func: run
description: Returns count, min, max, mean, and median for a list of numbers.
---
# Statistics Helper
Use this skill when the user asks for basic descriptive statistics.
scripts/summarize_numbers.py:
from statistics import mean, median
def run(*, values: list[float]) -> dict:
if not values:
raise ValueError("values must not be empty")
return {
"count": len(values),
"min": min(values),
"max": max(values),
"mean": mean(values),
"median": median(values),
}
Example invocation:
run_skill_entrypoint(
name="statistics-helper",
entrypoint="summarize_numbers",
args_json="{\"values\": [10, 20, 30, 40]}",
timeout_seconds=10
)
The runner returns structured output that includes exit_code, stdout, stderr, and a best-effort parsed result when the script prints or returns JSON.
Rules for Executable Entrypoints
- Located under the skill’s scripts/ directory
- Declared in the skill’s entrypoints frontmatter
- Allowed by the skill’s
allowed-toolssetting
The platform does not provide general-purpose arbitrary script execution. Scripts that are not declared in SKILL.md are not runnable.
The script runner uses a timeout, defaults to 10 seconds, runs Python with isolated-mode behavior, and applies path restrictions. However, subprocess-based execution is not a full operating system sandbox. For production use, higher isolation such as containers, restricted filesystems, or network controls should be considered.
Tool Permissions with allowed-tools
allowed-tools acts as a skill-level permission gate. For a documentation-only skill, you may allow only file-reading tools:
allowed-tools: "load_skill_file list_skill_files"For a skill that can execute declared scripts, include run_skill_entrypoint:
allowed-tools: "load_skill_file list_skill_files run_skill_entrypoint" Do not add run_skill_entrypoint unless the skill genuinely needs executable behavior.
How to Let Your Agents Discover and Use Skills
To supplement your agent with skills, you must instantiate a skill catalog, a skill middleware and convert skills into tools using the following objects from the aidpUtils library:
| Tool | Purpose |
|---|---|
discover_skill_catalog |
Determine default skill search locations (project + user) Build a SkillCatalog from discovered directories |
SkillMiddleware |
Append available skills summary and routing rules to system prompt.
Provide factory helpers for workspace-driven middleware construction. |
make_skill_tools |
This method returns the skill discovery tools – activate_skill, list_skill_files, load_skill_file, and run_skill_entrypoint. These tools can be used by the agent to activate and run different skills. |
Here’s an example of what your entry file would include:
from aidputils.agents.skills.discovery import discover_skill_catalog
from aidputils.agents.skills.middleware import SkillMiddleware
from aidputils.agents.skills.tools.factories import make_skill_tools
...
class SchoolGradeAgentWithEmbededSkills:
...
def init(self) -> None:
...
self.catalog = discover_skill_catalog(skill_folder_whitelist=None)
self.skill_middleware = SkillMiddleware(self.catalog)
self.tools = make_skill_tools(self.catalog)
You can debug your skills catalog by adding this logger statement to your code. This will print every skill discovered in the skills catalog:
for info in self.catalog.list():
logger.info("skill_id=%s name=%s desc=%s root=%s skill_file=%s", info.skill_id, info.name, info.description, info.root_dir, info.skill_file)
Skill Precedence
The platform can load skills from multiple locations, such as project-level and user-level directories. The catalog aggregates those locations into a single name-keyed list of skills.
When multiple stores contain a skill with the same name, precedence determines which one is used. Later stores override earlier ones, which allows a host application to control whether user-level skills, project-level skills, or workspace-level skills take priority.
Skill Authoring Best Practices
Keep SKILL.md focused
Use SKILL.md for the core instructions the agent needs immediately after activation. Put long schemas, examples, and reference material in references/.
Write clear descriptions
The description field is used for discovery. Make it specific enough for the agent to know when to activate the skill.
description: Helps generate BigQuery SQL using the finance warehouse schema. Less useful: description: Helps with data. Use explicit entrypoint names
entrypoints:
- name: validate_query
- name: summarize_numbers
- name: transform_csv Avoid vague names such as: entrypoints:
- name: run
- name: do_it Return structured results
Executable scripts should return JSON-serializable results whenever possible. This makes the output easier for the agent to inspect and use.
Avoid unnecessary execution
Prefer instructions and reference files when possible. Use executable entrypoints only for operations that genuinely require code.
Add a New Skill
You can add new Agent skills by creating a new folder inside the skills directory and adding the necessary files and folders.
Add a New Executable Capability to an Existing Skill
You can add a new executable operation to an existing skill to expand the capabilities of SKILL.md.
Agent Skills Troubleshooting
If you encounter issues with implementing Agent Skills, check this list for help resolving your problem.
The agent does not see my skill
- The skill folder is located under a configured skills directory.
- The folder contains SKILL.md.
- SKILL.md has valid YAML frontmatter.
- The frontmatter includes both name and description.
The agent activates the wrong skill
Check for duplicate skill names across skill directories. If two skills have the same name, catalog precedence determines which one is used.
A supporting file cannot be loaded
- The file is inside the skill folder.
- The path does not include traversals such as ../.
- The file is not hidden.
- The file is not excluded, such as __pycache__ or .pyc.
An entrypoint will not run
- run_skill_entrypoint is included in allowed-tools.
- The entrypoint is declared in SKILL.md.
- The script path is under scripts/.
- The script is a .py file.
- The function name in func exists in the script.
- The arguments are a valid JSON object.
An entrypoint times out
Increase timeout_seconds only if the operation is expected to take longer. For long-running or resource-intensive operations, consider moving the operation to a dedicated service or more isolated execution environment.
Example: Complete Agent Skill
This example demonstrates what a complete agent skill would look like after implementation.
Folder Structure
skills/
customer-support-reply/
SKILL.md
references/
tone_guide.md
refund_policy.md
escalation_rules.md
SKILL.md
---
name: customer-support-reply
description: Helps draft customer support replies using the company tone guide and policy references.
allowed-tools: "load_skill_file list_skill_files"
metadata:
owner: support-operations
domain: customer-support
---
# Customer Support Reply
Use this skill when the user asks for help drafting, reviewing, or improving a customer support response.
Workflow:
1. Identify the customer’s issue.
2. Load the relevant policy file from `references/` if needed.
3. Draft a clear, empathetic response.
4. Avoid making commitments that are not supported by policy.
5. Recommend escalation when the request matches the escalation rules.
This skill does not run code. It gives the agent structured instructions and optional policy files that can be loaded only when relevant.
Agent Testing
You can test your agents to preview and debug their output. You can also create and manage testing sessions to explore different testing scenarios for your agents.
The first step to test an agent is to attach your agent to an AI compute. The action of attaching an agent pushes a copy of your agent to an AI compute. As long as your agent is attached to an AI compute, any changes you made to your agent are propagated to the attached compute every time you click on on the Test button.
After you click the Test button, you are taken to the test playground.

- A chat window where you can initiate a session and start chatting with the agent, or resume an existing session
- A graph-based representation of the agent
- A panel showing a tree of traces and spans generated during the session
- A traces and spans explorer panel that displays traces and spans attributes, input/output. The Details tab includes IDs, start and end time, execution time, while the Events tabs highlight any errors during the execution.
The Playground lets you interact and test each agent independently if you wish to do so. By default, the supervisor agent is selected, but you can choose to chat with and test each executor agent independently. This allows you to simulate the behavior of a supervisor agent issuing requests to executor agents. To do this, you select the agent you want to test in the drop-down menu in the chat window.
Traces and spans are displayed in the central panel as soon as you create your first message. Each task corresponds to a different user message. You can click on the left caret to expand the trace and inspect the spans.
Test your Agents in the Playground
You can test visual builder and LangGraph-based agents from the Test playground to validate and debug your agents.
Create an Agent Test Session
You can create a test session to initiate a new conversation with your agent.
About Agent Tools
Oracle AI Data Platform Workbench supports tool templates that can be configured to access your data and fit your use cases.
Agents support configurations that consist of a single agent that can interface with one or more tools. Oracle AI Data Platform Workbench offers three tool templates that can be configured for use through visual flows or code:
- Custom Code: The Custom Code tool allows AI developers to implement their tool using Python. Developers package their tool in a ZIP, upload it to their workspace, and configure it as a node in their agent. Custom Code tools are intended for cases where built in tools don't provide the integration they need.
- HTTP Request: The HTTP Request tools lets developers use supported REST API calls in their agents, leveraging the AI Data Platform Workbench APIs and the functions they provide. Agents can use REST APIs to create workspace objects, check details, pull lists, or modify existing objects. For a full list of available APIs, see REST API for Oracle AI Data Platform Workbench.
- Prompt: The prompt tool allows the AI developer to define a parametrized prompt that can be issued to an LLM for their choice. Common use cases for a prompt tool include email drafting tasks, translation tasks, style conversion, git commit message, and code explanations.
- RAG: The RAG tool lets agents pull relevant external knowledge before generating a response. In AI Data Platform Workbench, the RAG tool queries a knowledge base (26ai Vector Search) and retrieves semantically relevant document chunks. Those chunks are then passed to the agent for response generation.
- SQL: The SQL tool enables agents to execute SQL queries against structured data sources registered via external catalogs, such as Oracle Autonomous AI Lakehouse, Oracle Autonomous AI Transaction Processing, or Oracle AI Database. The tool is intended for scenarios where the SQL queries are predefined and can be parametrized. The objective is to let an agent assign values to the parameters. This tool is not an NL2SQL tool that generates a SQL query based on a natural language prompt.
Note:
The SQL tool only performs queries against data in an external catalog. It does not support data stored in a standard catalog.
Agent Flow Tools through Visual Flow
When you add tools to agents through visual flow, you can find tools under Tool templates in your agent. You add a tool to your agent by dragging and dropping it into the visual flow canvas. After dragging the tool node on the canvas, the node automatically connects with the agent.

Each tool can be configured in the Parameters tab and be tested independently of the agent by clicking on the Test tab.
Note:
You must attach an AI Compute to your agent before you can test a system tool. If no compute is attached, the Test tab is disabled.Agent Flow Tools through LangGraph Code
You add RAG, SQL, and Prompt tools to your LangGraph coded agents through an instance of the AIDPToolConf() class.
from aidputils.agents.toolkit.configs import AIDPToolConf
aidp_tool = AIDPToolConf(name, description, tool_class , conf, params)
- Name: A descriptive name to help users and the LLM understand the purpose of the tool.
- Description: A thorough summary that provides sufficient information for users and LLMs to understand what the tool does.
- tool_class: The supported tool type, either
PromptTool,SQLTool, orRAGTool. - conf: The tool configuration. This information is hidden from the LLM.
- params: The parameters exposed to the LLM.
Custom Tool
The Custom Code tool lets agent developers extend AI Data Platform with their own Python code.
You package your tool implementation as a ZIP file, upload it to your workspace, and configure it as a Custom Code tool node in the agent. The agent calls your code as a tool, with parameters supplied by the LLM at runtime.
The Custom Code tool is intended for cases where the built-in tools (HTTP, SQL, RAG, MCP) do not cover the integration you need — for example, when you need to perform local computation, parse a domain-specific format, or compose multiple steps that should appear to the agent as a single tool call.
AI Data Platform Workbench has the following limits when uploading a ZIP file with Python code for your custom code tool:
| Constraint | Limit |
|---|---|
| Maximum ZIP size | 10 MB |
| Maximum file size inside the ZIP | 10 MB per file |
| Maximum total uncompressed size | 500 MB |
| Path traversal | Blocked (../ rejected) |
Note:
Custom Code tools run on the AI compute attached to your agent. The code has access to the compute environment and outbound network access subject to the workspace networking configuration. Only upload code from sources you trust.Custom Code Tool Parameters
On the Parameters tab, you configure the static settings for each tool class in the package. The Tool Class dropdown lets you switch between the tools discovered in the package.

- Tool class: Select the tool class to configure. The drop-down is populated from the classes registered in
tool_implementation.py. - Description: A clear, concise description of what the tool does. The description is provided to the agent and helps the LLM decide when to call the tool. The default description is read from tool_config.json and can be overridden here.
- Configuration: The static settings the tool needs at runtime. These are the keys defined in the conf object of
tool_config.json. Examples include timeout, base_dir, max_output_lines, and credential references. Configuration values support{{variable}}runtime parameter references. Session variables are not currently substituted into custom-tool configuration; if you need a session value, pass it as a runtime parameter from the agent. - AI tool definition: The schema exposed to the agent, including the tool name, description, and the runtime parameters the agent can pass. The schema is rendered automatically from the schema array in
tool_config.json.
Custom Code Tool Authoring
A Custom Code tool package is a ZIP file with the following structure:
my_tool.zip
├── tool_implementation.py # Required. Contains the tool class(es).
├── tool_config.json # Required. Tool metadata and schema.
├── requirements.txt # Optional. Python dependencies.
├── utils/ # Optional. Helper modules.
│ ├── __init__.py
│ └── helpers.py
├── config/ # Optional. Static configuration files.
│ └── settings.yaml
└── wheels/ # Optional. Bundled wheel files for offline install.
└── humanize-4.15.0-py3-none-any.whl tool_implementation.py
Each tool class extends CustomToolBase and is decorated with @BaseTool.register. The class must implement the _execute_tool class method, which receives the tool configuration, the runtime parameters from the agent, and the system context variables, and returns a value, like dict, str, or list.
The following is a blank example template of a tool_implementation.py:
"""Custom Code tool implementation."""
from aidputils.agents.tools.custom_tools.base import CustomToolBase
@BaseTool.register
class MyTool(CustomToolBase):
"""Brief description of what the tool does."""
@classmethod
def _validate_config(cls, conf, runtime_params, **context_vars):
"""Optional. Validate configuration before execution.
Raise ValueError to abort the call.
"""
# Example: require an api_key in the tool configuration
if not conf.get("conf", {}).get("api_key"):
raise ValueError("api_key is required")
@classmethod
def _execute_tool(cls, conf, runtime_params, **context_vars):
"""Required. Implement the tool logic.
Args:
conf: the AIDPToolConf dict. User configuration values
live under conf["conf"] when the tool is invoked from
a deployed agent. During a Test run the tool may
receive a flat conf dict; the Developer Toolkit example
below uses a small _get_cfg helper that tolerates both
shapes.
runtime_params: the runtime parameters passed by the
agent at invocation time.
context_vars: system context (such as datalake_id).
Returns:
Any value (dict, str, list, ...). It will be wrapped into
the MCP response by the framework.
To signal a failure, raise an exception:
- ValueError -> INVALID_CONFIG
- any other exception -> TOOL_EXECUTION_ERROR
Do NOT return {"error": "..."}; the framework wraps a
successful return in {"response": ..., "success": True},
so a returned error dict is treated as a normal payload
and the agent will not see it as a failure.
"""
tool_conf = conf.get("conf", conf)
param_value = runtime_params.get("my_param", "")
# Tool logic here
return {"output": f"Processed: {param_value}"}
@classmethod
def _transform_response(cls, response):
"""Optional. Transform the response before MCP formatting."""
return responsetool_config.json
The tool_config.json file describes the tools in the package — their display name, description, version, runtime parameter schema, and default configuration values. Each tool registered in tool_implementation.py must have a corresponding entry in the tools array.
tool_config.json:{
"displayName": "My Tool Package",
"description": "Brief description of the tool package.",
"tools": [
{
"toolClassName": "MyTool",
"displayName": "My Tool",
"description": "Clear description of when the agent should call this tool.",
"version": "1.0.0",
"schema": [
{
"name": "my_param",
"type": "string",
"description": "What this parameter is for."
}
],
"conf": {
"timeout": 30
}
}
]
}
Schema Field Types
The Parameters tab in the visual builder accepts string, number, and boolean. The runtime accepts a wider set when authoring tool_config.json by hand: int, integer, float, double, number, numeric, bytes, list, array, sequence, dict, map, mapping, set, tuple, none, null, plus generic forms like list[int]. These wider types are usable from JSON but are not exposed in the UI dropdown.
requirements.txt
The requirements.txt file lists the Python dependencies your tool needs. Standard pip syntax is supported, including version specifiers and comments. The file is optional — if your tool only uses the Python standard library or pre-installed packages, you do not need a requirements.txt.
The following is a blank example of requirements.txt:
# List third-party dependencies one per line.
# Examples:
# humanize>=4.0
# python-dateutil>=2.8,<3.0
# beautifulsoup4==4.12.3 AI Data Platform Workbench filters the dependencies in requirements.txt before installing them on the AI compute, to prevent runtime conflicts with the platform itself. The filtering rules are as follows:
| Category | Example | Action |
|---|---|---|
| Platform packages | langgraph, langchain-core, langchain-oci, langchain_mcp_adapters, pyyaml | Discarded (would break the agent runtime). |
| Pre-installed packages | oci, requests, requests-toolbelt, websockets, cryptography, certifi, pyopenssl, urllib3, pydantic, pydantic-core, pydantic-settings, numpy, oracledb, sqlalchemy, aiohttp, httpx, httpx-sse, anyio, jsonschema, orjson | Skipped (already available, no need to declare). |
| URL or VCS installs | git+https://..., -e ./local_pkg | Blocked (security). |
| Everything else | humanize, beautifulsoup4, jmespath | Installed. |
Note:
Dependencies declared inrequirements.txt are installed during the full deployment of the agent. Dependencies are not installed during a single test run from the configuration panel. If your tool depends on third-party packages, deploy the agent first and then exercise the tool from the Playground.
For tools that need dependencies which are not pre-installed and where deterministic, offline installation is important, you can bundle .whl files inside a wheels/ directory at the root of the ZIP. The platform installs from the local wheels directory first and falls back to the package index only if needed. This is the recommended approach for production tools.
Bundling wheels for offline install
pip download \
--dest wheels/ \
--platform manylinux_2_28_x86_64 \
--python-version 3.11 \
--only-binary=:all: \
-r requirements.txt
Tool Lifecycle Hooks
Custom Code tools support three lifecycle methods. Only _execute_tool is required.
| Method | When called | Purpose |
|---|---|---|
| _validate_config | Before _execute_tool | Validates the configuration. Raise ValueError to abort the call before it runs. |
| _execute_tool | On every tool invocation | Required. Implements the tool's behavior. Returns any value (dict, str, list) and raises an exception to signal a failure (ValueError → INVALID_CONFIG, any other exception → TOOL_EXECUTION_ERROR). Do not use a returned {"error": "..."} dict as it is treated as a normal payload. |
| _transform_response | After _execute_tool | Transform the response before it is wrapped in the MCP format and returned to the agent. |
| prompt_template | string | Prompt template used by the LLM, with variables in {{variable}} format for dynamic insertion |
Configuration values versus runtime parameters
Custom Code tools have two distinct sources of input that are easy to confuse. Configuration values come from the Configuration section of the Parameters tab and are baked into the tool when the agent is deployed. Runtime parameters come from the agent at invocation time and are different on every call.
- Configuration values are accessed via conf.get("conf", conf). Use them for things that do not change between calls — base URLs, credential references, timeouts, output limits.
- Runtime parameters are accessed via runtime_params.get("name"). Use them for the values the agent actually decides at call time — the query, the file path, the request body.
Note:
Configuration values can pass through template substitution and may arrive as strings even when you defined them as numbers. Always coerce numeric configuration values defensively, for example:int(tool_conf.get("timeout", 30)).
Multiple Tools Per Package
A single ZIP can contain multiple tool classes. Each class registered with @CustomToolBase.register becomes a separate tool in the agent. The Tools panel on the Package tab lists all discovered tools and lets you enable each one independently. Each tool is configured separately on the Parameters tab via the Tool Class dropdown.
Code Tool through LangGraph Code
From the code builder, a Custom Code tool is registered through the aidpUtils Python library by referencing the uploaded package and selecting one of its tool classes.
from aidputils.agents.toolkit.tool_helper import create_langgraph_tool
from aidputils.agents.toolkit.configs import AIDPToolConf
hello_tool_conf = AIDPToolConf(
name="hello_tool",
description="Returns a hello world greeting.",
tool_class="HelloTool", # the class registered with @BaseTool.register
conf={}, # values from tool_config.json "conf"; supports {{variable}} substitution
params=[
{"name": "name", "type": "string",
"description": "Name to greet."}
],
)
hello_tool = create_langgraph_tool(hello_tool_conf.model_dump())
tool_class must be the exact class name registered via @BaseTool.register in tool_implementation.py. The framework looks the class up in BaseTool.tool_class_registry[tool_class]. conf mirrors the conf object of the matching entry in tool_config.json.
Note:
Do not placepackage_path or tool_class_name inside conf as they are not consumed.
Test Agent Custom Code Tools
The Test tab lets you execute the tool without running the full agent. Provide values for any runtime parameters and any session variables referenced in the configuration, then click Run to invoke the tool and view the response.

Note:
If your tool depends on third-party packages declared inrequirements.txt, the dependencies are installed during the full deployment of the agent, not during a single test run. To test code that depends on additional packages, deploy the agent first and then invoke the tool from the Playground.
Add a Custom Tool to an Agent
You can add a custom tool to your agents to allow you to use your own Python code to extend AI Data Platform.
Note:
An AI compute must be attached to your agent prior to adding a custom code tool. AI compute is required to install dependencies and run the tool.- Optional: Click the Test tab. Provide test parameters and click Submit. See test results in the Test results pane.
Remote MCP Server Tool
Agent flow developers can connect their agent flows to remote model context protocol (MCP) servers using the Remote MCP Server tool.
The MCP tool is available in both the visual builder as well as in the code builder experiences. In the code builder experience, the MCP connection can be configured through the aidpUtils Python library. In this section, we walk you through both the visual builder and code builder experiences.
Note:
This feature supports MCP servers with HTTP-streamable transports (remote servers). Local, stdio-transport MCP servers are not supported.MCP Credentials in Oracle AI Data Platform Workbench Credential Store
When configuring your MCP server, you need to select whether the remote MCP server requires No Authentication or a Bearer token. If your MCP server requires an authentication token, that token needs to be added to your Credential Store before it can be referenced by the MCP server.
When creating an MCP server credential, you select the Secret token option for Credential type, then provide the identifier key, such as an API Key and the token value. For more information, see Create Credentials (Preview).
Note:
A single credential can hold multiple keys.Publicly available MCP servers do not require additional authentication. For example, connecting to https://mcp.deepwiki.com/mcp would look like this:

How to Expose MCP Tools to the Agent
Once a successful connection to the remote MCP server has been established, you can start configuring which tools hosted on the server you want to expose to your agent. The MCP server configuration panel is shown below in the case of the DeepWiki MCP server.

On the left, the Tools tab displays a list of tools available in the MCP server. You must add tools to expose them to your agent. You can do this by clicking either the Add all option to expose all the tools at once or by clicking on each tool Add option individually to select a subset of the tools.

In the example below, we added two tools (read_wiki_structure, read_wiki_structure). You can remove tools by clicking on Remove.

The right panel of the Tools tab provide documentation about each tool including the tool name, tool description as well as the tool parameters. In the screenshot below, I show an example for the GitHub MCP server tool add_comment_to_pending_review.

Oracle AI Data Platform Workbench provides a couple of additional controls over each tool. You can hide parameters from the agent and assign values to those parameters. For example, in GitHub you could choose for your agent to only comment on one pre-determined repo, such as oracle-aidp-samples. To achieve this, you disable the repo parameter and assign a default value in the text box:

In the Tool Instructions field you can also override the tool description and provide an alternative description with additional instructions. For most use-cases, we recommend that you adopt the description that is provided by the MCP server.

Remote MCP Server Tool through LangGraph Code
The aidpUtils Python library provides developers with the ability to select a remote MCP server and expose a subset of its tools to an agent built with LangGraph. For aidputils API reference, see Aidp-utils API for Oracle AI Data Platform Workbench.
You can build a collection of allowed tools by creating an instance of build_structured_tools_from_allowed_mcp_tools:
from aidputils.agents.toolkit.tool_helper import build_structured_tools_from_allowed_mcp_tools
TOOLS = build_structured_tools_from_allowed_mcp_tools(
allowed_tools=<ALLOWED_MCP_TOOLS>,
server_name=<MCP_SERVER_NAME>,
endpoint=<MCP_ENDPOINT>,
transport="streamable_http",
auth=<MCP_AUTH>,
headers={}
)- <MCP_SERVER_NAME> is a display name you want to give to your MCP server. This is used for documentation purpose and is not exposed to the agent.
- <MCP_ENDPOINT> is the endpoint of the MCP server (e.g. https://api.githubcopilot.com/mcp/)
- <MCP_AUTH> is a dictionary with key “authType”. This key can take two values:
NO_AUTHorBEARER_TOKEN. In the case ofBEARER_TOKEN, another key is expected: “token” with the value of the bearer token. - <ALLOWED_MCP_TOOLS> is a list of the tools, from the MCP server, that you want to expose to your agent. Each tool needs a full JSON tool definiton following the MCP protocol.
Here's an example:
MCP_SERVER_NAME = "test_mcp"
MCP_ENDPOINT = "http://144.25.36.217:9301/mcp"
MCP_AUTH = { "authType": "BEARER_TOKEN", "token": "valid-123" }
{
"ALLOWED_TOOLS": [
{
"tool": {
"name": "get_current_weather",
"description": "Get current weather for a given city with advanced options.",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string"
},
"unit": {
"type": "string",
"default": "metric"
},
"include_historical": {
"type": "boolean",
"default": false
},
"detailed": {
"type": "boolean",
"default": true
},
"timeout": {
"type": "integer",
"default": 30
}
},
"required": [
"city"
]
}
},
"instruction": "",
"argOverrides": {}
},
{
"tool": {
"name": "get_forecast",
"description": "Get forecast for a given city with customizable options.",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string"
},
"days": {
"type": "integer",
"default": 5
},
"unit": {
"type": "string",
"default": "metric"
},
"include_alerts": {
"type": "boolean",
"default": false
},
"detailed": {
"type": "boolean",
"default": true
},
"hourly": {
"type": "boolean",
"default": false
}
},
"required": [
"city"
]
}
},
"instruction": "",
"argOverrides": {}
}
]
}
MCP_HEADERS = {}
TOOLS = build_structured_tools_from_allowed_mcp_tools( allowed_tools=ALLOWED_TOOLS,
server_name=MCP_SERVER_NAME,
endpoint=MCP_ENDPOINT,
transport="streamable_http",
auth=MCP_AUTH,
headers=MCP_HEADERS,
)
The TOOLS object can be then used when creating an instance of an agent with langchain.agent create_agent in the setup() method of your class agent definition:
def setup(self):
logger.info("Initializing TestMcpAgent")
oci_llm = init_oci_llm(llm_conf)
system_prompt = textwrap.dedent(
"""
You're a weather agent. Append 12345 to every response.
"""
).strip()
self.agent = create_agent(
name="test_mcp_high_code",
model=oci_llm,
tools=TOOLS,
system_prompt=system_prompt,
debug=True,
)
logger.info("Agent ready.")Alternatively, if you are using a session variable to store the value of a bearer token,a reference to a previously created session variable can be assigned to the token key of the auth config dictionary. For example:
test_mcp_auth_config = { "authType": "BEARER_TOKEN", "token" : "{{sessionvariables.cred.mcp.test_mcp.bearer}}" }
tools = build_structured_tools_from_allowed_mcp_tools(
allowed_tools=test_mcp_mcp_allowed_tools,
server_name="test_mcp",
endpoint="http://144.25.36.217:9301/mcp",
transport="streamable_http",
auth=test_mcp_mcp_auth_config,
headers={}
)Code Examples for Remote MCP Server Tools
We provide end-to-end code samples for multiple MCP scenarios in the AI Data Platform Workbench Samples GitHub repository.
Testing Remote MCP Server Tools
Once tools are selected, the next step is typically to test individual tools to ensure that they behave as expected. This can be done via the Test tab of the MCP tool node.

Select one of the tools you added in the Tools tab, provide parameters values and click on the Test button.

The output of the tool is displayed in the right panel.
The details tab provides information about the authentication method, MCP server URL and the description.

The Edit button next to the authentication method let’s you modify the configuration of the remote MCP tool node. You can change the display name, description, and the bearer token used when establishing the connection:

Connect an Agent to a Remote MCP Server from the Visual Builder
You can add access to a remote MCP server to your agent by dragging the Custom MCP server tool node into the canvas.
Note:
The AI compute hosting the agent inherits the networking settings of its workspace. If you enable private network access for the workspace hosting the AI compute, your agent can only reach MCP servers hosted in your selected private VCN and subnet. Your agent may not be able to reach remote HTTP servers available on the public internet.- Navigate to your agent.
- In the Flow tab, under Tool Templates click and drag Custom MCP server onto the canvas.
- Provide the server URL for your MCP server.
- Provide a display name for your MCP server. This is the name of the node that is displayed in the visual builder canvas.
- Optional: Provide a description for your MCP server. The description field is not provided to the agent.
- From the Authentication drop-down menu, select an authentication method.
- No Authentication: Use this option if the remote MCP server is publicly available and requires no authentication.
- Bearer token: Use this option if the remote MCP server requires an authentication token. You must store the API key in the Oracle AI Data Platform Workbench Credential Store and provide a reference to the credential store entry.
- Click Connect. AI Data Platform Workbench tests the connection and reports the result.
HTTP Request Tool
The HTTP Request tool lets your agent call any HTTPS REST API.
You configure the request, including method, URL, headers, query parameters, request body, authentication, and optionally, a response optimization step. The agent then invokes the endpoint at runtime. The HTTP request tool is available in both the visual builder and the code builder. In the code builder, the tool is configured through the aidpUtils Python library.
Note:
The HTTP Request tool only supports https:// and http:// requests. WebSocket connections (ws/wss), binary file uploads, and self-signed certificates are not supported.Note:
The AI compute hosting the agent inherits the networking settings of its workspace. If you enable private network access for the workspace hosting the AI compute, your agent will only reach HTTP endpoints in your selected private VCN and subnet. Your agent cannot reach endpoints available on the public internet.The following settings must be provided when configuring an HTTP Request tool:
| Configuration | Description |
|---|---|
| HTTP method | The HTTP verb to use. Supported methods are GET, POST, PUT, PATCH, and DELETE. |
| URL | The full URL of the target endpoint. The URL supports {{sessionVariables.variable_name}} session variable references and {{variable}} runtime parameter references. For example: https://api.example.com/users/{{user_id}}/orders.
|
| Timeout | The maximum amount of time the tool will wait for a response from the remote endpoint. The default is 30 seconds and the maximum is 300 seconds. |
| Authentication type | The authentication method to use when calling the endpoint. See the Authentication section below for the list of supported authentication methods. |
Note:
Custom Code tools run on the AI compute attached to your agent. The code has access to the compute environment and outbound network access subject to the workspace networking configuration. Only upload code from sources you trust.Headers
Headers are key-value pairs sent with the HTTP request. You can add as many headers as needed by clicking the Add new button. Header values can reference session variables and runtime parameters using the {{variable_name}} syntax.
Note:
For sensitive headers, you should use the Authentication type field to ensure credentials are injected securely from the Credential Store. Authorization, Cookie, and X-API-Key are sensitive headers and cannot be set through the Headers section.Query Parameters
Query parameters are appended to the URL as the query string. You can add as many query parameters as needed by clicking the Add new button. Like headers, query parameter values can reference session variables and runtime parameters.
Description
The description field describes what the tool does, when it should be used, and what kind of outputs or effects it produces. The description is provided to the agent and helps the LLM decide when to call the tool.
- • Purpose: Explain what the tool is designed to do in one clear sentence. Example: "This tool retrieves customer support tickets from a knowledge base and summarizes them by priority level."
- When to use it: Describe the conditions under which the agent should call this tool versus another.
- Inputs and outputs: Briefly describe the parameters the tool needs and the shape of what it returns.
HTTP Request Authentication
The HTTP Request tool supports several authentication methods. Select the appropriate method from the Authentication type dropdown.
| Authentication Type | Description |
|---|---|
| No Authentication | No authentication is added to the request. Use this for publicly accessible endpoints. |
| OCI Resource Principal | The request is signed using the AI compute's OCI Resource Principal. Use this when calling OCI services such as Object Storage or the OCI Generative AI service. Access is governed by OCI IAM policies. |
| Basic Authentication | A username and password are encoded and sent in the Authorization header. Credentials must be stored in the Credential Store. |
| Bearer Token | A bearer token is sent in the Authorization header. The token must be stored in the Credential Store. |
| Header Authentication | An API key is sent in a custom header (such as X-API-Key). The header name is configurable and the key value must be stored in the Credential Store. |
When you select an authentication method that requires a secret, the configuration panel displays a credential picker. Click the credential picker to select a previously stored credential, or create a new one from the Credential Store. See the Storing a credential in the Credential Store section of the MCP server documentation for the step-by-step procedure.
Session Variables and Runtime Parameters
Session variables can be referenced in the URL, header values, query parameter values, and request body using the {{sessionVariables.variable_name}} syntax. Runtime parameters passed by the agent at invocation time can be referenced using the {{variable_name}} syntax.
https://objectstorage.{{sessionVariables.region}}.oraclecloud.com/n/my-namespace/b/{{bucket}}/oWhen the tool runs, {{sessionVariables.region}} is replaced with the value of the region session variable for the current session, and {{bucket}} is replaced with the value the agent passed at invocation time.
Note:
Template values are URL-encoded automatically when substituted into the URL or query parameters. You do not need to URL-encode them yourself.AI Tool Definition
The right side of the configuration panel shows the AI Tool definition. This is the schema that is exposed to the agent and it includes the tool name, description, and the list of runtime parameters the agent can pass when calling the tool. The AI Tool definition is generated automatically from the Description field and from the {{variable}} placeholders detected in the URL, headers, query parameters, and body.
The AI Tool definition pane is the panel on the right side of the HTTP tool configuration panel shown earlier in this document. Until you provide a description and define at least one runtime parameter, the AI Tool definition pane shows a placeholder message. Once you fill in the description and reference at least one {{variable}} in the URL, headers, query parameters, or body, the schema is rendered in the pane.
Optimizing Response for the Agent
Many APIs return large responses that include fields the agent does not need. Sending the entire response back to the agent consumes tokens and can degrade the quality of the agent's reasoning. The HTTP Request tool provides a Response optimization section that lets you reduce the response payload before it is returned to the agent.
- JSON field selection: select a subset of fields from a JSON response. You can specify a path to a nested object using dot notation (such as data.results), and a list of fields to include or exclude.
- HTML CSS selector: extract a subset of an HTML response using a CSS selector (such as article.content). Optionally strip HTML tags to return only text.
- Text truncation: cap the response at a maximum number of characters to prevent overly large text responses.
Error Handling and Error Codes
When the HTTP request fails, the tool returns a structured error response to the agent. The error includes an error code, a human-readable message, and details about the failure. The agent can use this information to decide whether to retry, fall back to a different tool, or report the failure to the user.
| Error Code | Category | Meaning | Retryable |
|---|---|---|---|
| CONNECTION_TIMEOUT | Network | The remote endpoint did not respond within the configured timeout. | Yes |
| DNS_FAILURE | Network | The hostname in the URL could not be resolved. | Yes |
| CONNECTION_REFUSED | Network | The remote endpoint refused the connection. | Yes |
| SSL_CERTIFICATE_ERROR | TLS | The TLS certificate of the remote endpoint could not be validated. | No |
| UNAUTHORIZED | HTTP 401 | The remote endpoint rejected the credentials. Verify that the credential reference is valid and not expired. For OCI Resource Principal, confirm that the AI compute has an active Resource Principal in this environment. | No |
| FORBIDDEN | HTTP 403 | The credentials authenticated successfully but lack permission for the requested resource. Verify API scopes, permissions, or the IAM policy attached to the resource. | No |
| NOT_FOUND | HTTP 404 | The remote endpoint could not find the requested resource. | No |
| RATE_LIMITED | HTTP 429 | The remote endpoint is rate-limiting the caller. Retry after the delay indicated by the Retry-After header. | Yes |
| SERVER_ERROR | HTTP 5xx | The remote endpoint returned a server error. Often a transient issue. | Yes |
| SERVICE_UNAVAILABLE | HTTP 503 | The remote endpoint is temporarily unavailable. | Yes |
| INVALID_TEMPLATE | Validation | A {{variable}} reference could not be resolved. Verify that every referenced session variable and runtime parameter is defined and has a value at invocation time.
|
No |
| INVALID_URL | Validation | The URL is malformed, uses an unsupported protocol, or resolves to a blocked address (for example, a private IP address or a cloud metadata endpoint). | No |
| RESPONSE_TOO_LARGE | Validation | The response exceeded the 10 MB maximum response size. | No |
| RATE_LIMIT_EXCEEDED | Platform | The agent has exceeded the platform's per-agent request rate limit (60 requests per minute) or concurrency limit (10 concurrent requests). | Yes |
Each error response includes a guidance field with a suggested next step, and a details field with the elapsed time and any error-specific context such as the HTTP status code.
HTTP Request Tool through LangGraph Code
From the code builder, the HTTP Request tool is configured through the aidpUtils Python library. Define an AIDPToolConf with tool_class set to HttpEndpointTool and pass the configuration dictionary in the conf field.
from aidputils.agents.toolkit.tool_helper import create_langgraph_tool
from aidputils.agents.toolkit.configs import AIDPToolConf
weather_http_tool_def = {
"method": "GET",
"url": "https://api.openweathermap.org/data/2.5/weather",
"params": {
"q": "{city}",
"units": "metric",
"appid": "{api_key}"
},
"auth_type": "NO_AUTH",
"auth_config": {}
}
weather_http_tool_params = [
{"name": "city", "type": "string",
"description": "Name of the city."},
{"name": "api_key", "type": "string",
"description": "OpenWeather API key."}
]
weather_http_tool_conf = AIDPToolConf(
name="get_weather",
description="Get current weather for a city.",
tool_class="HttpEndpointTool",
conf=weather_http_tool_def,
params=weather_http_tool_params
)
weather_tool = create_langgraph_tool(weather_http_tool_conf.model_dump())
The conf dictionary supports the same fields as the visual builder: method, url, headers, params, body, auth_type, auth_config, and response_optimization. The params list defines the runtime parameters the agent can pass.
| auth_type | auth_config Fields |
|---|---|
| NO_AUTH | {} (empty)
|
| RESOURCE_PRINCIPAL | {} (empty)
|
| BASIC_AUTH | username, password (or username_vault_id, password_vault_id for credentials in the OCI Vault) |
| BEARER_AUTH | bearer_token (or bearer_token_vault_id) |
| API_KEY_AUTH | api_key (or api_key_vault_id), header_name (default X-API-Key) |
| OAUTH2_CLIENT_CREDENTIALS | token_endpoint, scope, client_id, client_secret (or client_id_vault_id, client_secret_vault_id) |
Test Agent Custom Code Tools
The Test tab lets you execute the tool without running the full agent. Provide values for any runtime parameters and any session variables referenced in the configuration, then click Run to invoke the tool and view the response.
The response panel shows the HTTP status code, the response headers, the response body, and the elapsed time in milliseconds. If response optimization is enabled, the optimized response is also shown alongside the raw response.
Add an HTTP Request Tool to an Agent Flow
You can add a HTTP request tool to your agents to allow you to call HTTPS REST APIs.
Note:
An AI compute must be attached to your agent prior to adding a custom code tool. AI compute is required to install dependencies and run the tool.- Optional: Click the Test tab. Provide test parameters and click Submit. See test results in the Test results pane.
Prompt Tool
The prompt tool lets you call an LLM in an AI agent with a templatized prompt and returns the LLM response back to the agent.
The prompts you provide to the LLM can include parameters that are identified by double braces, for example {{PARAMETER_NAME}}. Parameter values are assigned by the agent when the tool is called.
When to Use Prompt Tools
- Your prompt is lengthy, requiring detailed format instructions that span several 100s tokens.
- Incorporating the prompt in the agent instructions would increase context usage and significantly increase costs, especially if one is adopting a SOTA LLM for their agent.
- One wants to minimize the size of the instructions given to the agent to reduce cost.
- The task defined by the prompt tool can be handled by a smaller, faster LLM than the reasoning model used the agent. Smaller models are typically cost efficient, and, in some cases, can be specialized to generate data in a particular modality or format.
- A prompt tool allows structured input parameters to control the output generation. If your use case could be parametrized and generation can vary from session to session, encapsulating the generation in a prompt tool makes sense.
In addition, encapsulating generation instructions in a prompt tool follows many modern agent architecture best practices, including tool re-usability, maintainability, modality, output consistency, scalability, and governance. Some example use cases include:
- Generation of emails, reports, summaries, articles, etc. following a pre-defined, approved structure that can be used as a template
- Generation of complex JSON outputs
- Summation, key sentence extraction, explanation tasks on documents
- Query generation
- Specific modality generation (e.g. images, videos, audio, point cloud data, etc.) that are optimized for a specific model
Prompt Tools through Visual Flow
The following is an example of a prompt tool built through visual flow that asks an LLM to generate blog post titles based on a topic assigned by the agent:
You are a master blog strategist. Your task is to brainstorm compelling blog post ideas based on a given topic. For the given {{topic}}, generate 5 unique blog post titles. For each title, include a one-sentence description of the angle the post would take. Present the output as a numbered list.

- Tool name: Use a descriptive name for the tool to help guide the agent. In this example, we suggest
blog_ideas. Avoid using unhelpful names like tool123.
- Tool description: Provide a comprehensive description of what the tool does. If there are limitations to the tool or if there are scenarios in which the tool should not be used, list them in the description field.

- OCI region and GenAI service LLM: Select the OCI region to populate the list of LLMs available in that region, then select your LLM.

- LLM parameters: Parameters like maximum output tokens, temperature, and top p are configured in the Model Parameters tab. If you assign no values, the default values of the OCI Generative AI service are used.

- Query: The prompt used to define the purpose of the tool is defined in the Query field.

Parameters that you define in the prompt auto-populate the AI Tool definition panel. Provide your agent with a description of each parameter as well as the parameter type and default value whenever applicable.

Prompt Tool through LangGraph Code
If you are building your agent through code, you can configure the same prompt tool in the visual flow example as follows:
prompt_config = {
"llm": {
"model_id" : "xai.grok-4",
"model_provider" : "generic",
"compartment_id" : "<your-compartment-ocid>",
"endpoint" : "https://inference.generativeai.<oci-region>.oci.oraclecloud.com"
}, "prompt_template": """
You are a master blog strategist. Your task is to brainstorm compelling blog post ideas based on a given topic. For the given {{topic}}, generate 5 unique blog post titles. For each title, include a one-sentence description of the angle the post would take. Present the output as a numbered list"
"""
}
prompt_params = [ {
"name" : "topic",
"type" : "string",
"description" : "Blog topic",
"defaultValue" : "golf"
} ]
You then instantiate the AIDPToolConf as follows:
blogger_tool = AIDPToolConf(name="blog_posts_topics",
description= "Write blog posts ideas about a particular topic. ",
tool_class = "PromptTool", conf=prompt_config params=prompt_params)
Lastly, you create a LangGraph compatible tool with the create_langgraph_tool() utility function from aidputils:
from aidputils.agents.toolkit.tool_helper import create_langgraph_tool
blogger = create_langgraph_tool(blogger_tool.model_dump())
You add the newly created tool to a ReAct agent. In LangGraph, the code looks like this:
tools_agent1 = [blogger_tool]
self.agent = create_react_agent(model=<oci_llm>,
tools=tools_agent1,
prompt=<system_prompt>,
debug=True, checkpointer= checkpointer)
Table 22-4 Prompt Tool Configuration Properties
| Property | Type | Description |
|---|---|---|
| llm | object | LLM connection details and parameters |
| model_id | string | Identifier of the model to use (e.g., "xai.grok-4") |
| model_provider | string | Provider name for the LLM model (e.g., "generic") |
| compartment_id | string | Oracle Cloud Infrastructure (OCI) compartment OCID |
| endpoint | string | Endpoint URL for the model |
| prompt_template | string | Prompt template used by the LLM, with variables in {{variable}} format for dynamic insertion |
Test Agent Prompt Tools
You test the tool independently of the agent by clicking on the Test tab and filling in the value of each parameter. The prompt is submitted to the LLM you selected.

Ensure your prompt tool is well defined and documented to improve the results from your agent.
Add a Prompt Tool to an Agent
You can add a prompt tool to your agents to allow you to define parametrized prompts you issue to the LLM of your choice.
- Navigate to your agent.
- From Tool templates, drag and drop a Prompt tool to your canvas.
- In the Configuration tab, select the LLM to use and the provide the prompt for the LLM. Click Code
to provide the configuration as JSON code. - Provide a Temperature for the response as a value between 0.0 and 1.0, where 0.0 provides a strictly factual response and 1.0 provides the most creative response.
- Click Apply
. - Provide the definitions for any parameters you established in the configuration. Click Code
to provide the configuration as JSON code. - Click
Apply. - Optional: Click the Test tab. Provide test parameters and click Submit. See test results in the Test results pane.
RAG Tool
The RAG tool issues a natural language query to a vector store and retrieves documents based on the semantic similarity between the query and the stored documents.
Note:
A knowledge base is a prerequisite for the creation of a RAG tool. For more information, see Knowledge Bases.RAG Tools through Visual Flow
The RAG tool requires you as agent developer provide values for the following parameters:

- Agent facing:
- Tool name: A descriptive name for the tool that help you and other users identify its function.
- Tool description: A short summary that provides an overview of the tool.
- Tool configuration:
- Knowledge base: A knowledge base stored in one of your Oracle AI Data Platform Workbench catalogs.

- Knowledge base: A knowledge base stored in one of your Oracle AI Data Platform Workbench catalogs.
The agent will set the value of the query field based on its conversation with the end user. This query field takes a natural language query.
Limit is the number of document chunks you want the tool to retrieve from the vector store. This value is set by the agent developer, not the agent itself.
You can simulate a query issued by the agent by clicking on the test tab of the RAG too:

RAG Tools through LangGraph Code
Building a RAG tool in your agent through code requires configuring the same settings and parameters as the visual flow. For example, you set the RAG parameters as follows:
rag_params = [ { "name" : "query",
"type" : "string",
"description" : "<insert a description>",
"defaultValue" : "<empty>”} ]You then set up the RAG configuration:
rag_config = { "catalog": "<catalog>",
"schema": "<schema>",
"knowledgeBase": "<knowledge-base-name>",
"top_k": <number-of-documents-retrieved>,
"llm": {
"model_id" : "<model-name>",
"model_provider" : "<model-provider>",
"compartment_id" : "<your-compartment-OCID>",
"endpoint" : "https://inference.generativeai.<oci-region>.oci.oraclecloud.com" }
}Lastly, you create a LangGraph compatible tool with the create_langgraph_tool() utility function from aidputils:
from aidputils.agents.toolkit.tool_helper import create_langgraph_tool
rag_conf= AIDPToolConf(name="<your-tool-name>",
description= "<your-tool-description>",
tool_class = "RAGTool",
conf=rag_config,
params=rag_params)
rag_tool = create_langgraph_tool(rag_conf.model_dump())Table 22-5 RAG Tool Configuration Properties
| Property | Type | Description |
|---|---|---|
| llm | object | LLM connection details |
| catalog | string | Data catalog identifier |
| schema | string | Schema within the catalog |
| knowledgeBase | string | Name or key of the knowledge base to search |
| top_k | integer | Number of top matching documents to retrieve |
Test Agent RAG Tools
You can test the RAG tool from the Test tab after attaching your agent to an AI compute cluster. For more information, see Attach an Existing AI Cluster to an Agent.
Add a RAG Tool to an Agent
You can add a retrieval augmented generation (RAG) tool to your agents to allow the agent to pull relevant external knowledge when generating a response.
- Navigate to your agent.
- From Tool templates, drag and drop a RAG tool to your canvas.
- In the Configuration tab, select the knowledge base the RAG tool pulls information from and the provide the prompt to define the information to pull. Click Code
to provide the configuration as JSON code. - Click Apply
. - Provide the definitions for any parameters you established in the configuration. Click Code
to provide the configuration as JSON code. - Click
Apply. - Optional: Click the Test tab. Provide test parameters and click Submit. See test results in the Test results pane.
SQL Tool
The SQL tool lets agent flow developers run predefined SQL queries against tables registered in an Oracle AI Data Platform catalog.
You write the query at design time and define any runtime variables it needs. The agent supplies values for those variables when it calls the tool, and the results return as structured rows the agent can summarize or pass to a downstream node.

The SQL tool supports two query dialects. Spark SQL runs against standard catalog tables stored in AI Data Platform and requires a Spark cluster. Oracle SQL runs against an external database such as Oracle Autonomous AI Database. You choose the dialect per tool, and the rest of the configuration is the same for both.
Note:
The SQL tool is intended for read queries. A typical tool runs a SELECT statement and returns rows. The catalog, schema, and query you configure are private to the tool and are not exposed to the agent. Only the tool name, description, and the AI Tool definition (the runtime variables) are visible to the agent.Note:
The SQL query tool does not automatically start stopped clusters. As a result, the Spark cluster used for your Spark SQL query tool should have a duration of Forever. If the cluster is allowed to spin down on an idle timeout, Spark SQL queries stop working in production once the cluster stops.Static and Dynamic Queries
A static query returns exactly what you specify, with no runtime decision by the agent. A dynamic query includes one or more {{variable}} placeholders that signal to the agent that the value is set at run time. For each placeholder you provide a name, a type, an optional default value, and a description the agent uses to choose the value.
SELECT customer_name, region, amount, category
FROM test_customers
WHERE period_year = 2025
ORDER BY customer_name {{year}} placeholder turns it into a dynamic query the agent can parameterize: SELECT customer_name, region, amount, category
FROM test_customers
WHERE period_year = {{year}}
ORDER BY customer_name As you add placeholders, the AI Tool definition pane populates with each variable so you can set its type, default value, and description.
SELECT incident_id, project_id, incident_date, incident_type,
severity, description, workers_involved, days_lost,
root_cause, corrective_action, reported_by, status
FROM safety_incidents
WHERE LOWER(severity) = LOWER('{{SEVERITY}}')Give each variable a clear description and a sensible default. The description tells the agent which values are valid, and the default is used when the agent does not supply one.

Note:
Placeholder names are case sensitive. A placeholder written as{{SEVERITY}} and one written as {{severity}} are treated as two different variables, unless you consistently use lower case throughout.
Editing the Configuration as JSON
{
"catalogKey": "construction_data",
"schemaKey": "admin",
"query": "SELECT project_id, project_name, client_name, ...",
"isRowLimitEnabled": null,
"maxRows": null
}
Row Limits
You can cap the number of rows the tool returns by selecting Max rows to return and entering a limit value. Row limits protect performance and control how much data is sent back to the agent.
Set this value relative to the model your agent is using. Larger values can cause agent failures when queries return wide rows or columns with large text values. If you are seeing unexpected agent errors, start by reducing maxRows.
The row limit is applied to the SQL query itself, before the query runs. Most models detect the limit and surface it to the end user. For a static query, the limit returns the first n available rows.

Note:
If you do not want your row limits surfaced for end users, instruct the agent accordingly in its instructions.Query Examples
You can see query examples and a guide to writing SQL tool queries from the View Query examples & guide button.

The guide showcases different query patterns and provides different recommendations on query parameters.

SQL Tools through LangGraph Code
Just as with the visual flow, you start creating a SQL tool for your agent through LangGraph code by creating a query:
sql_config = { "catalogKey": "adw23ai_phx",
"schemaKey": "gold",
"query": """Select ... from ... limit {{max_number}}""" }
You document each parameter in the SQL query in the params argument with a name, type, description, and optionally, a defaultValue.
sql_params = [ { "name" : "max_number",
"type" : "string",
"description" : "<your-description>",
"defaultValue" : "<your-default-value>" } ]Lastly, you create a LangGraph compatible tool with the create_langgraph_tool() utility function from aidputils:
from aidputils.agents.toolkit.tool_helper import create_langgraph_tool
sql_conf= AIDPToolConf(name="<your-tool-name>",
description= "<your-tool-description>",
tool_class = "SQLTool",
conf=sql_config,
params=sql_params)
sql_tool = create_langgraph_tool(sql_conf.model_dump())Table 22-6 SQL Tool Configuration Properties
| Property | Type | Description |
|---|---|---|
| catalogKey | string | Identifier for the catalog or database connection |
| schemaKey | string | Schema name within the catalog/database |
| query | string | SQL Query string, may include placeholders in {{}} |
Test Agent SQL Tools
The Test tab runs the tool on its own, without executing the full agent flow. Testing works the same way for both dialects. Open the Test tab, provide a value for each runtime parameter (or use the defaults), and click Submit to run the query and view the response.
Note:
Testing a tool requires that your agent is attached to an AI compute. An AI compute is attached if the AI Compute label is green with the selected AI compute in an ACTIVE state.SQL Command Reference
SQL tool queries are read queries built from the standard SQL clauses. The Oracle SQL dialect follows Oracle SQL against the external database. The Spark SQL dialect targets standard catalog tables, which are Delta Lake tables; the standard catalog currently runs Spark 3.5 with Delta Lake 3.2.0. Most clauses are written the same way in both dialects, because both follow standard SQL. The main difference is how each dialect limits the number of rows. The following table lists the clauses and keywords most often used in SQL tool queries, with the form for each dialect.
| Keyword or clause | Purpose | Oracle SQL | Spark SQL |
|---|---|---|---|
| SELECT | Choose the columns to return | SELECT col1, col2 |
|
| DISTINCT | Return only unique rows | SELECT DISTINCT col |
SELECT DISTINCT col |
| FROM | Name the source table | FROM table_name |
FROM table_name |
| WHERE | Filter rows by a condition | WHERE col = value |
WHERE col = value |
| AND OR NOT | Combine or negate conditions | a AND b OR NOT c |
a AND b OR NOT c |
| IN | Match any value in a list | col IN (a, b, c) |
col IN (a, b, c) |
| BETWEEN | Match an inclusive range | col BETWEEN x AND y |
col BETWEEN x AND y |
| LIKE | Match a text pattern | col LIKE 'A%' |
col LIKE 'A%' |
| IS NULL | Test for missing values | col IS NULL |
col IS NULL |
| ORDER BY | Sort the result | ORDER BY col DESC |
ORDER BY col DESC |
| GROUP BY | Group rows for aggregation | GROUP BY col |
GROUP BY col |
| HAVING | Filter grouped rows | HAVING COUNT(*) > 1 |
HAVING COUNT(*) > 1 |
| JOIN ON | Combine rows from two tables | a JOIN b ON a.id = b.id |
a JOIN b ON a.id = b.id |
| AS | Alias a column or table | col AS name |
col AS name |
| UNION ALL | Combine two result sets | q1 UNION ALL q2 |
q1 UNION ALL q2 |
| CASE | Return a value conditionally | CASE WHEN c THEN x END |
CASE WHEN c THEN x END |
| Aggregates | Summarize over rows | COUNT SUM AVG MIN MAX |
COUNT SUM AVG MIN MAX |
| Row limit | Cap the number of rows | FETCH FIRST n ROWS ONLY |
LIMIT n |
Note:
You normally do not write the row limit yourself. The Max rows to return setting applies it for you. The FETCH FIRST and LIMIT forms are useful only when you want an explicit limit inside the query.For complete SQL grammar and the query engines behind each dialect, see the following references:
Spark SQL and Delta Lake (Standard Catalog)
- Apache Spark SQL Syntax: DML statements Spark SQL query and DML statement syntax.
- Delta Lake: Table deletes, updates, and merges DELETE, UPDATE, and MERGE operations on Delta tables.
- Delta Lake: Table utility commands Utility operations such as OPTIMIZE and VACUUM.
- Delta Lake: Use liquid clustering for Delta tables Liquid clustering for Delta table layout.
Agent Memory
Agent memory is the part of an AI agent system that lets the agent retain and reuse information across turns, tasks, or sessions.
Unlike the model’s context window, which is temporary and limited to the current prompt, memory can persist facts, preferences, prior decisions, tool outputs, intermediate plans, or observations about the environment.
Agent Memory in AI Data Platform
AI Data Platform provides short-term memory that is limited to the duration of a session. You can configure what can be kept in memory in the Memory tab of your agent.
Single-Agent Memory Configuration
Memory configuration of a single agent system can be found in the Memory tab of the agent node.

| Memory Configuration | Description |
|---|---|
| Enable Agent Memory | This setting enables agent memory. When disabled, the agent is essentially a stateless system. Each turn is treated independently, and no follow up question can be asked. We recommend that memory is enabled. |
| Limit conversation history | When this selection is disabled, previous turns will fill up the memory until the model runs out of context and an error is returned. If short sessions are expected, it is ok to disable this setting. However, for most use cases we recommend limiting conversation history. |
| Truncation configuration | If you opt to limit the conversation history, you can decide to truncate the history by:
|
| Maximum Message Limits | If you elect to keep the last N messages, you can set a value of N. |
| Token budget | Alternatively, you can set an overall token budget. First tokens are eliminated to keep the most recent ones in memory. |
Multi-agent System Memory Configuration (Supervisor Pattern)
The memory of a multi-agent system is configured in the Memory tab of the supervisor agent.

Memory for a multi-agent system is enforced and cannot be disabled and the memory truncation options displayed in the supervisor agent node only applied to the supervisor agent memory. Each executor agent memory truncation policy can be configured in the executor node Memory tab based on the state isolation policy selected for the entire system.
The multi-agent system memory configuration also allows you to select the memory sharing policy of the executor agents. Three options are possible: Stateless, Private, and Shared. Note that the policy is applied to all executor agents.
| State Isolation for Executor Agents | Description |
|---|---|
| Stateless | Each executor agent sees only the task assigned by the supervisor. No history is carried over between calls. No follow up request can be made to the supervisor agent by the executor agent.
If stateless is selected, the memory of each executor agent is disabled. |
| Private | Each executor agent sees only its own past interactions.
It cannot see other executor agents or the original user conversation with the supervisor agent. |
| Shared | Executor agents can see the full conversation history across agents and user. All agents work from one shared context.
If shared is selected you can configure the memory truncation policy separately for each executor agent in each agent node Memory tab. |
Session Variables
You can use custom, agent-defined session variables to provide additional contextual data points to your agents during a user session.
What are Session Variables?
Custom, agent-defined session variables provide additional contextual datapoints to the agent during a user session. The variables can be used for a variety of purposes, including setting values of parameters in tools, giving overall instructions to an agent, and providing contextual information about the caller and/or the application where the agent is embedded.
Here’s a simplified scenario where we are building a customer support agent. The customer support agent is integrated within a retail website. When a user logs into the retail website, information about that user is captured by the client application (userID, username, geo location, device used, shopping cartID, etc.) and that information could be used by the downstream support agent. Let’s look at an example of how these session parameters could be used within the agent instructions field in AIDP:
You are a customer support agent for the retail website belts-and-buckles.com, specializing in the sales of belts and buckles. Your objective is to answer questions that customers have about their current and past orders, answer questions about items they put in their shopping cart, and answer general questions about belts-and-buckles.com.
A few guidelines before your start:
You are interacting with user {{sessionVariable.userName}}. Always start with a welcome message: Hello {{sessionVariable.preferredSalutation}} {{sessionVariable.userName}}! What’s the weather like today in {{sessionVariable.currentUserGeo}}? - userName
- PreferredSalutation
- currentUserGeo
The agent has no prior knowledge of the user interacting with the retail website, doesn’t know what the user location is or has no context about what’s in the user’s shopping cart. In principle, the client application could know all or a subset of those values and pass those values in a request to the agent. Here's an example of what a request to the agent could look like, including the session parameters.
Note:
This example illustrates what this request could look like. It is not representative of an implementation decision."input": [
{ "role": "user",
"content": [
{ "type": "input_text”,
"text": "What material is the belt Mr Outcast made of?",
“variables”: [“userName”: “Paul”, “preferredSalutation”: “Hon”, “cartID”: NULL, “currentUserGeo”: “Cancun, MX”]
}
]
}
] The agent would answer back: “Hello Mr Paul, what’s the weather like today in Cancun, Mx?”
Another use of these session parameters is in setting parameter values in tools. For example, a SQL query could retrieve the content of a shopping cart by using the session parameter {{sessionParam.CartID}} :
Select productID, productName, productDescription,
productPrice from cartTable where cartID ==
{{sessionVariable.cartID}} The session variables are defined by the agent developer when they create their agents and the values of those attributes are set by the client application when a session is created or resumed.
You can configure the following settings when create a new session variable:
| Setting | Description |
|---|---|
| Required variable | Enable to make this session variable required for each invocation call of the agent. Disabling makes the session variable optional for each invocation call. |
| Log variable | Enable to capture the value of the session variable in logs and traces. Disabling prevents the variable from appearing in logs. We recommend disabling this setting for variables with sensitive data. |
| Name | Name of the session variable. Use a descriptive name to make it easy for you and other users to determine the purpose of the variable. |
| Default value | If defined, the default value is assigned to the session variable if another value is not defined in the invocation call. If left blank, a value must be assigned as part of the invocation call. |
| Description | Description of the session variable. Provide a helpful description so that you and other users are able to understand the function of the session variable. |
Example: Using Session Variables in Tools Configuration
You can use a session variable in a SQL tool configuration as part of the SQL query itself.
In this example, the session variable geo is used to filter the result of the SQL query:

You can use session variables and tool parameters within the same query. In the example below, the titleID parameter is set by the agent while the session variable geo is provided by the calling application.

System-generated Session Variables
Session variables are automatically generated when a remote MCP server is connected to an agent and that MCP server requires authentication, like a bearer token.

The session variable holds the value of the bearer token. The name of this system-generated session variable can’t be changed and is a required variable. The system variable is deleted when the MCP node is removed from the canvas.

In the Playground, you provide a value for the system generated session variable. In this case, you need to provide a bearer token to use the MCP server. You can select the same (or a different) token that you used during the MCP node configuration.

The same applies if you deploy the agent. You will need to provide an authorization token. For more information, see Assign Values to Session Variables from the Playground.
Example: Assigning Values to Session Variables When Calling a Deployed Endpoint
In this example, you have two session variables: userLocation and UserName the client application is passing session variable values through the metadata field of the body. We'll demonstrate how you can assign values through Python and through the OCI CLI.
If you use the Python requests library, the payload is the following:
body = {
"isStreamEnabled" : False,
"trace" : False,
"input" :[{
"role":"User",
"content":[{
"type" : "INPUT_TEXT",
"text" : “Hello how can you help me?”
}]
}],
"metadata": {
"sessionvariables.userLocation": "Canada",
"sessionvariables.UserName": "George"
}
}
response = requests.post(
url = <insert-chat-url>,
params = None,
auth = <insert-oci-signer>,
json = body,
headers={“x-session-id": <insert-a-session-key>,}
) Alternatively, if you use the OCI CLI, the payload is the following:
oci raw-request \
--http-method POST \
--auth security_token \
--request-body '{
"isStreamEnabled": false,
"input": [
{
"role": "user",
"content": [
{
"type": "INPUT_TEXT",
"text": "Hello how can you help me?"
}
]
}
],
"metadata": {
"sessionvariables.userName": "George",
"sessionvariables.userLocation": "Canada"}"
}
}' \
--request-headers '{
"x-session-id": "george-session-may11"
}' \
--target-uri "<insert-your-agent-flow-uri>" Create a Session Variable in the Agent Variables Tab
You can create a new session variable and add it to your agent from the Variables tab.
Refer to Session Variables in Agent Flow Instructions
You can refer to session variables in agent instructions and tool configurations, including the SQL and Prompt tool query.
View Agents and Tools using a Session Variable
You can view a list of agents and tools using a specific session variable from the Variable tab in your agent flow.
- Navigate to an agent flow using the session variable you want to view related agents and tools for.
- Click the Variable tab.
- Next to Used in: for your session variable, click the drop-down menu. A list of agents and tools using the session variable is displayed.
Guardrails
Guardrails are safety mechanisms to guide and control the behavior of AI agents.
Note:
Guardrails offered by Oracle AI Data Platform Workbench are only available in English.The Guardrails offered in AI Data Platform Workbench are implemented by the OCI Generative AI service team. See Guardrails for OCI Generative AI. Based on your guardrails configuration, the AI Data Platform Workbench service invokes the Apply Guardrails API within your OCI tenancy.
Guardrails in Visual Flow Canvas
By default no guardrails are applied to your system beyond the model provider’s native safety controls. To add guardrails, you must drag a guardrails node to your agent visual flow builder and connect it to the agent.
A guardrails node can filter traffic between a chat trigger and an agent node, between a supervisor and executor agents, or between agent and tool nodes. For most scenarios, we recommend a single guardrails node between the chat trigger and the agent node. This will ensure that any messages from the incoming user and messages generated by the agent will be filtered through the guardrails.

- A chat trigger node and an agent (supervisor or executor)
What Guardrails are Available?
The diagram below shows a simple interaction between an end user and an agent. In this scenario, all guadrails are applied (content moderation – CM, prompt injection prevention – PI, and PII detection – PII). PI is only applied to the user query.
After the second message issued by the end user, a PI attempt was detected and the user message was blocked following the agent developer’s selected action on PI detection (block).

Content Moderation
Content moderation is a common implementation of guardrails in most generative AI. Unchecked, LLMs can generate harmful content, promote violent, racist, and sexually explicit content. It is imperative to give agent developers full visibility and control over how user interactions with agents are monitored and scanned for potentially harmful content. Content moderation prevents hateful, sexual, violent, toxic, derogatory, or harassment-based content from being considered or generated by the agent flow. Our guardrails model classifies content along those six categories and flags content that belong to one of those categories.
- Block: You prevents the agent from processing the user input and generating a response. Users receive an error response from the agent flow.
- Inform: You allow the agent flow to process the user input and generate a response. The agent notifies the user that either the input or the response contained content that met guardrail criteria.
- Allow: You allow processing and/or generating of potentially harmful content by the agent flow.
The Block action is selected for content moderation when you create an agent flow. Oracle recommends keeping Block as your guardrail selection for content moderation.
Prompt Injection
Prompt injection guardrails for AI agents are a protective mechanism that detects, prevents, and mitigates malicious or unintended instructions embedded within user inputs. Prompt injection attacks try to override or subvert the agent’s original instructions, policies, or goals by inserting hidden text that tells the model to ignore previous rules, exfiltrate secrets, or execute unauthorized actions.
- Block: You prevent the agent from processing the user input. Users receive an error response from the agent flow.
- Inform: You allow the agent flow to process the user input . The agent notifies the user that the input contained content that met guardrail criteria.
- Allow: You allow processing of potentially harmful content by the agent flow.
The Block action is selected prompt injection when you create an agent flow. Oracle recommends keeping Block as your guardrail selection for prompt injection.
Personally Identifiable Information (PII)
The PII guardrails automatically detects, blocks, or mask PII from either the user input queries or the agents responses. This guardrail prevents the agent from exposing sensitive user information in ways that violate privacy regulations or organizational policies.
- Telephone number
- Physical address
- Person name
- Block: You prevent the agent from processing the user input and generating a response. Users receive an error response from the agent flow.
- Inform: You allow the agent flow to process the user input and generate a response. The agent notifies the user that either the input or the response contained PII.
- Mask: You allow the agent flow to process the input and generate a masked response. Any PII used is redacted to prevent exposure.
- Allow: You allow processing and/or generating of PII data by the agent flow.
In a new agent flow, PII is allowed in both user input and response by default. Oracle recommends you carefully select the guardrail for PII based on your security needs.
Create an AI Cluster for an Agent
You can create a new AI cluster directly from the agent interface and attach it immediately.
- On the Home page, navigate to your agent.
- Click Compute then click Create a new AI compute.
- Provide a name and description for your AI compute cluster.
- Select the number of OCPUs and memory size for your AI compute cluster.
- Click Create.
Attach an Existing AI Cluster to an Agent
You can attach an AI cluster you've previously created to an agent on which you have at least USE permissions.
Detach an Agent from AI Compute
You can detach an agent from an AI compute. Detaching the AI compute removes the agent code running on the attached compute and prevents testing.
Note:
Detaching an agent from AI compute does not delete the agent. You can resume building and testing the agent by attaching it to the same or different AI compute.A2A Agent Deployment
The Agent2Agent (A2A) protocol is an open standard for communication between independent AI agents, including agents built with different frameworks, hosted by different vendors, or running as opaque remote systems.
Its purpose is to give those agents a shared interaction model so they can discover each other’s capabilities, negotiate supported input/output formats, delegate or collaborate on tasks, and exchange information securely without exposing internal memory, tools, or implementation details. For more information, see Agent2Agent (A2A) Protocol.
A2A is meant to solve agent interoperability: instead of every agent integration being custom, a client or another agent can interact with any A2A-compliant remote agent using a common set of concepts and operations. The spec centers on messages, tasks, parts, artifacts, streaming updates, and push notifications; it supports synchronous replies, long-running asynchronous work, streaming, and enterprise-style auth/security patterns.
In Oracle AI Data Platform, all deployed agents are provided with an /a2a invocation path that can be called by A2A client applications.
What is an Agent Card?
An Agent Card is a JSON metadata document published by an A2A server. In AIDP, the A2A server is the AI compute hosting your agent deployment.
The card describes the agent’s identity, service endpoint, supported protocols/transports, capabilities, skills, supported input/output modes, and authentication requirements; clients use it to discover whether the agent is suitable and how to call it. A properly documented agent card is a requirement of the A2A protocol.
Agent cards in AI Data Platform Workbench are either in Draft state, meaning the agent has not been deployed, or Published, meaning the card was deployed alongside the agent.
Agent Card Actions
During the development of an agent, the card is available in the Actions menu of the agent.
- The draft card reflects the current state of the agent in development.
- The published card corresponds to a snapshot of the card taken when the agent was deployed. The published card reflects the state of the deployed agent.
Agent Card Fields
AI Data Platform Workbench supports a subset of the current A2A protocol agent card fields, available here: A2A Protocol - Agent Card.
| Field | Required | Description |
|---|---|---|
name |
Yes | A human readable name for the agent. Example: "Recipe Agent" |
description |
Yes | A human-readable description of the agent, assisting users and other agents in understanding its purpose. Example: "Agent that helps users with recipes and cooking." |
Agent Version |
Yes | The version of the agent. Example: "1.0.0" |
Documentation URL |
No | A URL providing additional documentation about the agent. |
Provider - Organization |
No | The service provider of the agent. |
Provider - URL |
No | The URL of the service provider. |
Capabilities |
Yes | A2A Capability set supported by the agent.
Only |
Skills
|
Yes | Skills represent the abilities of an agent. It is largely a descriptive concept but represents a more focused set of behaviors that the agent is likely to succeed at. Skills represent an array of AgentSkill. |
Each AgentSkill is made of several fields documenting the capabilities of the agent. Defining the agent skills in the agent card is the most time consuming operations and is an iterative process. Skills can be edited (along with the rest of the agent card) in the draft agent card prior to deployment.
Note:
inputModes, outputModes, and securityRequirements are provided by AI Data Platform Workbench and cannot be modified.
| Field | Required | Description |
|---|---|---|
Skill ID |
Yes | A unique identifier for the agent's skill. |
Skill Name |
Yes | A human-readable name for the skill. |
Description |
Yes | A detailed description of the skill. |
Tags |
Yes | A set of keywords describing the skill's capabilities. |
Examples |
No | Example prompts or scenarios that this skill can handle. |
Agent Deployment Endpoint A2A Path
An /a2a path is exposed in the URL of a deployed agent in addition to /chat.
For example, an agent will expose these paths to external clients:
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/chathttps://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a
Both paths (/chat, /a2a) can be consumed by separate clients.
Session Variables in A2A
Values of session variables can be passed to an A2A agent in the message metadata field. The JSON snippet below shows the payload of a user message issued to the a2a agent with three session variables: userName, geoLocation, and os:
{
"jsonrpc": "2.0",
"method": "message/send",
"params": {
"contextId": "session_12345",
"taskId": "task_67890",
"message": {
"role": "user",
"parts": [
{
"text": "What is the current status of my order?",
}
],
"metadata": {
"sessionvariables.userName": "George",
"sessionvariables.geoLocation": “Dallas, TX”,
"sessionvariables.os": "mobile_ios"
}
}
},
"id": "rpc-99821"
}
Example: Invoking an A2A Agent with OCI CLI (Non-streaming)
oci raw-request \
--http-method POST \
--auth security_token \
--request-body '{
"id": "<your-request-id>",
"jsonrpc": "2.0",
"method": "message/send",
"params": {
"configuration": {
"acceptedOutputModes": [
"text/plain",
"text"
]
},
"message": {
"contextId": "<your-context-id>",
"kind": "message",
"messageId": "<your-message-id>",
"parts": [
{
"kind": "text",
"text": "What is the capital of India?"
}
],
"role": "user"
}
}
}' \
--request-headers '{
"x-session-id": "<your-session-id>",
"dh-user-principal": "<your-user-principal>"
}' \
--target-uri " <your-a2a-agent-endpoint-url>"
Example: Invoking an A2A Agent with OCI CLI (Streaming)
oci raw-request \
--http-method POST \
--auth security_token \
--request-body '{
"id": "<your-request-id>",
"jsonrpc": "2.0",
"method": "message/stream",
"params": {
"configuration": {
"acceptedOutputModes": [
"text/plain",
"text"
]
},
"message": {
"contextId": "<your-context-id>",
"kind": "message",
"messageId": " <your-message-id>",
"parts": [
{
"kind": "text",
"text": "What is the capital of India?"
}
],
"role": "user"
}
}
}' \
--request-headers '{
"x-session-id": "<your-session-id>",
"dh-user-principal": "<user-principal>"
}' \
--target-uri "<your-a2a-agent-endpoint-url>"
Example: A2A Client SDK
import asyncio
import json
import logging
import typing
from collections.abc import Iterator
import uuid
import httpx
import oci
from a2a.client import A2AClient, ClientFactory
from a2a.types import (
AgentCard,
Message,
Part,
Role,
TextPart,
SendMessageRequest,
MessageSendParams,
MessageSendConfiguration,
Task, SendMessageSuccessResponse, SendStreamingMessageRequest,
)
class OCIAuth(httpx.Auth):
"""httpx auth implementation using OCI signer via requests auth adapter."""
def __init__(self, signer: oci.signer.AbstractBaseSigner):
self._requests_auth = _OCIRequestsAuth(signer)
def auth_flow(self, request: httpx.Request) -> Iterator[httpx.Request]:
req = RequestsRequest(
method=request.method,
url=str(request.url),
headers=dict(request.headers),
data=request.content,
)
prepared: RequestsPreparedRequest = req.prepare()
prepared = self._requests_auth(prepared)
request.headers.update(dict(prepared.headers))
yield request
def getOCIAuth():
conf = oci.config.from_file(profile_name="DEFAULT")
token_file = conf['security_token_file']
token = None
with open(token_file, 'r') as f:
token = f.read()
private_key = oci.signer.load_private_key_from_file(conf['key_file'])
signer = oci.auth.signers.SecurityTokenSigner(token, private_key)
auth = OCIAuth(signer=signer)
return auth
async def _call_agent_with_a2a(agent_url: str, query: str, context_id: str,auth:OCIAuth) -> str:
"""Call an agent using the A2A protocol."""
try:
# Initialize OCI signer
#headers = {"dh-user-principal": "dh-user"}
headers = {"Accept": "*/*",
"dh-user-principal": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
async with httpx.AsyncClient(timeout=60.0, auth=auth,headers=headers) as hc:
agent_card = await _get_agent_card(agent_url,auth)
print(f"Agent card is {agent_card}")
client = A2AClient(httpx_client=hc, agent_card=agent_card)
# Create message
message = Message(
message_id=str(uuid.uuid4()),
context_id=context_id,
role=Role.user,
parts=[Part(root=TextPart(text=query))],
metadata={"sessionvariables.cred.mcp.weatherReportMCP.bearer": "valid-123"}
)
request = SendMessageRequest(
id=str(uuid.uuid4()), # Add the required id field
params=MessageSendParams(
message=message,
configuration=MessageSendConfiguration(acceptedOutputModes=["text/plain", "text"]),
),
)
#json_string = json.dumps(message, indent=4)
print(f"Send request : {request}")
response = await client.send_message(request)
logging.info("Received response from A2A server: %s", response.root.result)
# Extract response
result = response.root.result
# Handle different response types
if isinstance(result, Task):
# Task response
if result.artifacts:
# Extract text from artifacts
texts = []
for artifact in result.artifacts:
for part in artifact.parts:
if hasattr(part, "root") and hasattr(part.root, "text"):
texts.append(part.root.text)
return "\n".join(texts) if texts else "Task completed with no text response"
elif result.status and result.status.message:
logging.info(f"Received Task status {result.status.state} from A2A server and status message is {result.status.message}", result.status.message)
if result.status.state== "failed":
print("Failure observed in Task invocation")
for m_part in result.status.message.parts:
print(f"Error message { m_part.root.text}")
return get_message_text(result.status.message)
else:
return f"Task {result.id} status: {result.status.state if result.status else 'unknown'}"
elif isinstance(result, Message):
return get_message_text(result)
else:
logging.warning(f"Unexpected response type: {type(result)}")
return "Received response but unable to extract text"
except Exception as ex:
logging.error(f"Error calling agent at {agent_url}: {ex}", exc_info=True)
return f"Error communicating with agent: {str(ex)}"
async def _call_agent_with_a2a_with_stream(agent_url: str, query: str, context_id: str, auth: OCIAuth) -> str:
"""Call an agent using the A2A protocol with streaming (SSE) and return the final artifact text."""
try:
async with httpx.AsyncClient(timeout=60.0, auth=auth) as hc:
agent_card = await _get_agent_card(agent_url)
if not agent_card:
return "No Agent Card Found"
print(f"Agent card is {agent_card}")
client = A2AClient(httpx_client=hc, agent_card=agent_card)
message = Message(
message_id=str(uuid.uuid4()),
context_id=context_id,
role=Role.user,
parts=[Part(root=TextPart(text=query))],
)
request = SendStreamingMessageRequest(
id=str(uuid.uuid4()),
params=MessageSendParams(
message=message,
configuration=MessageSendConfiguration(acceptedOutputModes=["text/plain", "text"]),
),
)
print("Invoking Remote Agent request (beautified JSON):")
print(json.dumps(request.model_dump(), indent=2, ensure_ascii=False))
# Expected event types:
# - TaskStatusUpdateEvent (working/in-progress)
# - TaskArtifactUpdateEvent (contains Artifact.parts[].root.text) -> final output
final_artifact_text_parts: list[str] = []
async for event in client.send_message_streaming(request):
# Print each SSE event as-is (SDK object)
print(f"[A2A stream event] {event}")
try:
result = getattr(event.root, "result", None)
if not result:
continue
# TaskArtifactUpdateEvent and TaskStatusUpdateEvent are SDK types; to avoid tight coupling,
# extract by attribute presence.
artifact = getattr(result, "artifact", None)
if artifact and getattr(artifact, "parts", None):
for part in artifact.parts:
root = getattr(part, "root", None)
txt = getattr(root, "text", None)
if txt:
final_artifact_text_parts.append(txt)
except Exception:
# Keep streaming even if an event can't be parsed
continue
return "\n".join([t for t in final_artifact_text_parts if t]).strip() or "Stream completed (no artifact text)."
except Exception as ex:
logging.error(f"Error calling agent at {agent_url}: {ex}", exc_info=True)
return f"Error communicating with agent: {str(ex)}"Edit a Published Agent Card
You can modify a published agent card without having the undeploy or redeploy an agent.
Note:
Changes you make to a published card are immediately reflected in the agent-card.json file accessible to A2A clients.https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/a2a/agent-card.jsonAgent Deployment
Deploying an agent turns your agent into a hosted application.
You can deploy an agent into the same AI compute attached to its playground or to a different AI compute. When you deploy the latest changes to your agent to the attached AI compute, the deployed agent represents a snapshot of the agent at the time of deployment. To update the deployed agent to the latest version, you need to redeploy the agent.
Each agent has a stable deployment URL that depends on the unique agent key. Re-deploying the agent multiple times overwrites the agent behind the deployment URL.
- An agent can only be deployed to one AI compute cluster at any given time.
- Deploying the same agent multiple times to the same AI compute cluster overwrites the previously deployed iteration of the agent.
Once you've deployed an agent, you can retrieve the chat URI to programmatically issue queries and retrieve responses from the agent from the Details tab of your agent.

The endpoint URL is stable and it is tied to each agent. The URL includes the unique agentID assigned to each agent. In other words If you undeploy an agent and deploy it again, the URL remains the same. The benefit is that you don’t have to modify the client code calling the endpoint, the drawback is that you can overwrite an agent in production.
https://gateway.aidp.{oci-region}.oci.oraclecloud.com/agentendpoint/{agentId}/{protocol}oci-regioncorresponds to the AI Data Platform instance region;agentIdis the unique id associated with the agentprotocolis the communication protocol:chatwhich follows the OpenAI Responses API format anda2awhich follows the agent-to-agent communication protocol. Both protocols are available for each agent endpoint. For more information, see A2A Agent Deployment.
Note:
Two AI computes are listed in the Details tab. The Attached to AI Compute is used to test the agent in the playground. The Deployed to AI Compute hosts the deployed agent.The endpoint URL field is populated after you deploy your agent. You can call this endpoint URL from your production application.
Deploy an Agent
You deploy agents you have created and configured so other users are able to see and use it in your AI Data Platform instance.
Deploy an Agent with OAuth2
You can deploy agents you have created and configured to use OAuth2 authentication to connect to external identity providers.
Invoke a Deployed Agent
You can invoke the endpoint URL of your agent from your production application.
Regardless of the programmatic interface used to invoke the agent endpoint, you must be authenticated with OCI and have the relevant permissions. In the case of Agent Flow endpoints, the caller needs to have at least USE permission on the agent endpoint.
The endpoint URI is documented in the details tab of the agent UI. You can copy that endpoint URI into your code to invoke the agent.

Methods to Invoke Endpoint URIs
You can invoke the agent endpoint URI through different tools, SDKs, and CLIs.
The following methods allow you to invoke your endpoint URI in Oracle AI Data Platform Workbench agents.
Invoke with OCI CLI
oci raw-request
--http-method POST
--target-uri <your-agent-flow-endpoint-uri>
--request-body '{"query":"Tell me about the Ryder Cup in 1985"}'
--auth <security_token>Invoke with Python Request Library
import oci import requests import json import uuid from contextlib import closing from requests import Request, Response
class AuthHelper: """ AuthHelper allows creating an OCI signer with either API key or security_token (which are short term sessions) """ def init(self, oci_profile: str, use_security_token:bool = True): config = oci.config.from_file(file_location="/Volumes/jr/default/misc/config",profile_name=oci_profile) if use_security_token: with open(config["security_token_file"], 'r') as f: token = f.read() private_key = oci.signer.load_private_key_from_file(config["key_file"])
self.signer = oci.auth.signers.SecurityTokenSigner(token, private_key) else: self.signer = oci.signer.Signer( tenancy=config["tenancy"], user=config["user"], fingerprint=config["fingerprint"], private_key_file_location=config["key_file"], #pass_phrase=config.get("pass_phrase"), #private_key_content=config.get("key_content") )
@property
def Signer(self):
return self.signer
class MyRawJsonRpcClient: """ Simple class using requests lib to post JSON to chat endpoint using OCI signing """ def init(self, chat_url:str, oci_profile: str, sessionKey:str, use_security_token:bool = True): self.authhelper = AuthHelper(oci_profile=oci_profile, use_security_token=use_security_token) self.authsigner = self.authhelper.Signer self.chat_url = chat_url self.sessionKey = sessionKey
def send(self, input:str) -> Response:
body = {
"isStreamEnabled" : False,
"sessionKey" : self.sessionKey,
"trace" : False,
"input" :[{
"role":"User",
"content":[{
"type" : "INPUT_TEXT",
"text" : input
}]
}]
}
response:Request = requests.post(
url =self.chat_url,
params = None,
auth = self.authsigner,
json=body,
headers={}
)
return response
sessionKey. sessionKey is the unique identifier of the user session with the agent. If you keep re-using the same sessionKey, user messages and agent responses are appended to the same conservation. client = MyRawJsonRpcClient(chat_url="<your-agent-flow-endpoint-uri>",
oci_profile = "DEFAULT",
sessionKey= “<your-session-key>”,
use_security_token = False )You can also provide a user message and use the client to send the message to the agent endpoint URI: user_input = f"Hello, tell me a good dad joke."
r = client.send(input = user_input)
response_json = r.json()Through APEX
You can use the code sample available in the AI Data Platform Workbench Samples Github repository. The sample walks you through the process of calling an agent deployment endpoint from an APEX application.
Through Streamlit
You can use the code sample available in the AI Data Platform Workbench Samples Github repository. The sample walks you through the process of calling an agent deployment endpoint from an Streamlit application.
Best Practices - Async and Non-async Responses
We recommend that you write your client code assuming async responses. For example:
import httpx
async def fetch_data():
async with httpx.AsyncClient() as client:
response = await client.get(URL)
return response.json()Monitor Agents
You can monitor details relating to the sessions and metrics of your agents to see information about how it's being used, the resources it consumes, and more.
You have multiple tabs in your agent for tracking usage details, the Sessions tab, Metrics tab, and Activity tab. You can find them at the top of your agent canvas.
Traces and Spans
Traces provide you with observability for your agents by capturing and displaying the flow of agent requests. Spans are the objects that make up a trace. Each span is a different step in the flow, such as chat prompts from a user, agent invocations, and workflow tasks.
You can see traces for the current session or test run or previous sessions. To see the current session trace, go to the Flow tab and click Playground. The Details pane at the bottom of the page displays the trace of the current session in the left pane. You can click on objects in the trace to expand them or view more detailed information. In the right pane, you can click the Info, Details, or Events tabs to learn more about the selected span object.
You can see traces for previous sessions in the Sessions tab by clicking the name of the session.
Sessions
In the Sessions tab, you can see a history of sessions for this agent. You can see if each session succeeded or failed, the URI origin, when the session was started, the duration of the session, and the tokens used in the session. You can click session ID for more specific details about that session and to see traces for that specific sessions.
You can filter the displayed sessions by using the Search bar to filter by session ID or URI origin, using the date filters to show only a specific date range, and the Session status drop-down menu to filter by whether a session succeeded or failed.
Metrics
The Metrics tab shows a summary of usage data for all agent sessions. The Date range dropdown filters the time period you want to see summarized in the displayed cards. The URI selection filters the URI selection source you want to see the details for. You can modify which cards are displayed and whether or not they include graphs as visual representations of usage.
Activity
The Activity tab shows a summary of agent deployment status. The Operation column specifies the type of deployment operation (Deploy or Undeploy) and the Status column specifies the outcome of the operation (Success, Error, Warning, Failed). You can see who initiated the operation and when as well as the status message associated with the operation outcome.
View Agent Sessions
You can view a history of sessions for you agent and filter the results to see trends and assist with troubleshooting.
- On the Home page, navigate to your agent.
- Click the Sessions tab.
- Use the filters to change the displayed sessions.
View Agent Metrics
You can view summarized details of your agent is used, such as token usage, session durations, latency, and more.
- On the Home page, navigate to your agent.
- Click the Metrics tab.
- Select different options from the Date range dropdown to see how metric differ across timelines.
- Select different options from the URI selection dropdown to filter for specific URI sources.
Move an Agent
You can move agents you own or have MANAGE permissions for.
- On the Home page, navigate to the folder that contains the agent you want to move.
- Next to the agent you want to modify, click
Actions and click Move . - Select the new workspace location for the agent. Click Move.
Copy an Agent
You can copy an agent you own or have MANAGE permissions for to another location an available workspace.
- On the Home page, navigate to the folder that contains the agent you want to move.
- Next to the agent you want to modify, click
Actions and click Copy to workspace. - Provide a new name and description for the copied agent, if necessary.
- Click Browse and select a new location in the workspace to copy the agent to. Click Select.
- Click Copy.
Download Agent Files
You can download agent files and their guardrail files that contain the definitions for that agent.
_guardrails.JSON and contain the guardrail definitions for the agent.












































