Generate Text
Parameters
Section titled âParametersâThe uc_ai.generate_text() function has four overloaded signatures. Two of them
read the configuration from the package globals. The other two take a p_config
JSON object instead. See Config-driven variants.
Function Signatures
Section titled âFunction SignaturesâSignature 1: Individual Prompts
Section titled âSignature 1: Individual PromptsâFUNCTION generate_text ( p_user_prompt IN CLOB, p_system_prompt IN CLOB DEFAULT NULL, p_provider IN provider_type, p_model IN model_type, p_max_tool_calls IN PLS_INTEGER DEFAULT NULL, p_response_json_schema IN JSON_OBJECT_T DEFAULT NULL, p_run_context IN JSON_OBJECT_T DEFAULT NULL) RETURN JSON_OBJECT_T;Signature 2: Message Array
Section titled âSignature 2: Message ArrayâFUNCTION generate_text ( p_messages IN JSON_ARRAY_T, p_provider IN provider_type, p_model IN model_type, p_max_tool_calls IN PLS_INTEGER DEFAULT NULL, p_response_json_schema IN JSON_OBJECT_T DEFAULT NULL, p_run_context IN JSON_OBJECT_T DEFAULT NULL) RETURN JSON_OBJECT_T;Signatures 3 & 4: Config-driven
Section titled âSignatures 3 & 4: Config-drivenâThe same two shapes, each with an extra p_config parameter placed right after
p_model:
FUNCTION generate_text ( p_user_prompt IN CLOB, p_system_prompt IN CLOB DEFAULT NULL, p_provider IN provider_type, p_model IN model_type, p_config IN JSON_OBJECT_T, p_max_tool_calls IN PLS_INTEGER DEFAULT NULL, p_response_json_schema IN JSON_OBJECT_T DEFAULT NULL, p_run_context IN JSON_OBJECT_T DEFAULT NULL) RETURN JSON_OBJECT_T;
FUNCTION generate_text ( p_messages IN JSON_ARRAY_T, p_provider IN provider_type, p_model IN model_type, p_config IN JSON_OBJECT_T, p_max_tool_calls IN PLS_INTEGER DEFAULT NULL, p_response_json_schema IN JSON_OBJECT_T DEFAULT NULL, p_run_context IN JSON_OBJECT_T DEFAULT NULL) RETURN JSON_OBJECT_T;Parameter Reference
Section titled âParameter ReferenceâFor Signature 1 (Individual Prompts)
Section titled âFor Signature 1 (Individual Prompts)â| Parameter | Type | Required | Description |
|---|---|---|---|
p_user_prompt | CLOB | Yes | The main prompt from the user. This is the primary input for the AI model. |
p_system_prompt | CLOB | No | System-level instructions that guide the behavior and response style of the AI. |
p_provider | provider_type | Yes | AI provider to use. See uc_ai spec for constants. |
p_model | model_type | Yes | Specific AI model to use (varies by provider). See uc_ai spec for constants. |
p_max_tool_calls | PLS_INTEGER | No | Maximum number of tool calls allowed in the conversation (default: 10). |
p_response_json_schema | JSON_OBJECT_T | No | JSON schema for structured output. The response then conforms to this schema. |
p_run_context | JSON_OBJECT_T | No | Name/value pairs bound to this call. Every tool receives them under _ctx. See the run context. |
For Signature 2 (Message Array)
Section titled âFor Signature 2 (Message Array)â| Parameter | Type | Required | Description |
|---|---|---|---|
p_messages | JSON_ARRAY_T | Yes | Array of conversation messages in the standard format (see Message Structure below). |
p_provider | provider_type | Yes | AI provider to use. See uc_ai spec for constants. |
p_model | model_type | Yes | Specific AI model to use (varies by provider). See uc_ai spec for constants. |
p_max_tool_calls | PLS_INTEGER | No | Maximum number of tool calls allowed in the conversation (default: 10). |
p_response_json_schema | JSON_OBJECT_T | No | JSON schema for structured output. The response then conforms to this schema. |
p_run_context | JSON_OBJECT_T | No | Name/value pairs bound to this call. Every tool receives them under _ctx. See the run context. |
Parameter Details
Section titled âParameter Detailsâp_user_prompt (Required - Signature 1)
Section titled âp_user_prompt (Required - Signature 1)âThe main user input that you want the AI to respond to. This can be a question, instruction, or any text you want the AI to process.
l_result := uc_ai.generate_text( p_user_prompt => 'What is Oracle APEX?', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_luna);p_system_prompt (Optional - Signature 1)
Section titled âp_system_prompt (Optional - Signature 1)âSystem-level instructions that define the role, behavior, and response style of the AI. They shape how the AI reads a user prompt and how it answers.
-- Professional assistantl_result := uc_ai.generate_text( p_user_prompt => 'Explain database normalization', p_system_prompt => 'You are a professional database consultant. Provide clear, technical explanations with practical examples.', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_terra);
-- Casual tonel_result := uc_ai.generate_text( p_user_prompt => 'How do I optimize this SQL query?', p_system_prompt => 'You are a friendly database expert. Use simple language and provide step-by-step guidance.', p_provider => uc_ai.c_provider_anthropic, p_model => uc_ai_anthropic.c_model_claude_4_5_haiku);p_messages (Required - Signature 2)
Section titled âp_messages (Required - Signature 2)âA conversation that you build yourself, as a JSON_ARRAY_T of message objects. With it, you can give a complete conversation history, or continue an earlier conversation. Each message must follow the standard message format, with the role and content properties.
DECLARE l_messages JSON_ARRAY_T; l_result JSON_OBJECT_T;BEGIN -- Build conversation messages l_messages := JSON_ARRAY_T();
-- Add system message l_messages.append(JSON_OBJECT_T('{ "role": "system", "content": "You are a helpful SQL expert." }'));
-- Add user messages l_messages.append(JSON_OBJECT_T('{ "role": "user", "content": "How do I create a table in Oracle?" }'));
l_messages.append(JSON_OBJECT_T('{ "role": "assistant", "content": "You can create a table using the CREATE TABLE statement..." }'));
l_messages.append(JSON_OBJECT_T('{ "role": "user", "content": "Now show me how to add a foreign key constraint" }'));
-- Continue the conversation l_result := uc_ai.generate_text( p_messages => l_messages, p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_luna );END;/Message Structure: Each message in the array must have this structure:
role: One of"system","user","assistant", or"tool"content: The message content (can benullfor assistant messages with tool calls)tool_calls: (Optional) Array of tool calls for assistant messagestool_call_id: (Required for tool messages) the ID of the tool call that this message answers
Use Cases for Message Array:
- Continue previous conversations
- Implement conversation memory and history
- Fine-tune conversation context
- Handle complex multi-turn interactions
- Process conversation logs or transcripts
Usage Examples
Section titled âUsage ExamplesâChoosing Between Signatures
Section titled âChoosing Between SignaturesâUse Signature 1 (Individual Prompts) when:
- Starting a new conversation
- Making simple, single-turn requests
- You want the function to build the message array
Use Signature 2 (Message Array) when:
- Continuing an existing conversation
- You need fine control over the conversation structure
- Implementing conversation memory across multiple calls
- Processing pre-existing conversation logs
Simple Example: Question with System Prompt
Section titled âSimple Example: Question with System PromptâUsing Signature 1:
DECLARE l_result JSON_OBJECT_T;BEGIN l_result := uc_ai.generate_text( p_user_prompt => 'What are the benefits of using Oracle APEX?', p_system_prompt => 'You are an Oracle APEX expert consultant.', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_luna );END;/Advanced: Conversation Continuation
Section titled âAdvanced: Conversation ContinuationâThis example shows how to continue a conversation using the message array signature.
UC AI converts in both directions between the standard message format and the format of each provider. You can therefore change the provider and the model in the middle of a conversation.
declare l_messages json_array_t; l_result json_object_t; l_response_messages json_array_t;begin -- Initial conversation l_result := uc_ai.generate_text( p_user_prompt => 'What is the rarest chemical element?', p_system_prompt => 'You are an assistant for chemical students in school.', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_luna );
dbms_output.put_line('Response: ' || l_result.get_string('final_message'));
-- Get the complete message history from the first call l_messages := l_result.get_array('messages');
-- Add a follow-up question l_messages.append( uc_ai_message_api.create_simple_user_message( 'How is it called in german, japanese and portuguese?' ) );
-- Continue the conversation with full context l_result := uc_ai.generate_text( p_messages => l_messages, p_provider => uc_ai.c_provider_google, p_model => uc_ai_google.c_model_gemini_3_7_flash );
dbms_output.put_line('Follow-up response: ' || l_result.get_string('final_message'));END;Additional Parameter Details
Section titled âAdditional Parameter Detailsâp_provider (Required - Both Signatures)
Section titled âp_provider (Required - Both Signatures)âSpecifies which AI provider to use. Available providers:
| Provider Constant | Value | Description |
|---|---|---|
uc_ai.c_provider_openai | 'openai' | OpenAI GPT models |
uc_ai.c_provider_anthropic | 'anthropic' | Anthropic Claude models |
uc_ai.c_provider_google | 'google' | Google Gemini models |
-- Using different providersl_result := uc_ai.generate_text( p_user_prompt => 'Explain machine learning', p_provider => uc_ai.c_provider_openai, -- or c_provider_anthropic, c_provider_google p_model => uc_ai_openai.c_model_gpt_5_6_luna);p_model (Required - Both Signatures)
Section titled âp_model (Required - Both Signatures)âThe specific AI model to use. See the package headers for available models under each provider:
uc_ai_openaiuc_ai_anthropicuc_ai_google
-- Model selection examplesDECLARE l_result JSON_OBJECT_T;BEGIN -- For simple tasks - use fast, cost-effective models l_result := uc_ai.generate_text( p_user_prompt => 'Summarize this paragraph', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_luna );
-- For complex analysis - use more capable models (GPT-5.6 Sol, Claude Opus 5, Gemini 3.1 Pro) l_result := uc_ai.generate_text( p_user_prompt => 'Analyze this complex financial dataset and provide strategic recommendations', p_provider => uc_ai.c_provider_anthropic, p_model => uc_ai_anthropic.c_model_claude_5_sonnet );END;/p_max_tool_calls (Optional - Both Signatures)
Section titled âp_max_tool_calls (Optional - Both Signatures)âLimits the maximum number of tool calls the AI can make during the conversation. This prevents infinite loops and controls costs.
- Default:
NULL(10 tool calls)
-- Limiting tool callsl_result := uc_ai.generate_text( p_user_prompt => 'Calculate monthly sales totals and create a summary report', p_system_prompt => 'You have access to database tools to query sales data', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_terra, p_max_tool_calls => 5 -- Allow up to 5 tool calls);
-- Check if limit was exceededIF l_result.get_string('finish_reason') = 'max_tool_calls_exceeded' THEN DBMS_OUTPUT.PUT_LINE('Consider increasing max_tool_calls for this task');END IF;p_response_json_schema (Optional - Both Signatures)
Section titled âp_response_json_schema (Optional - Both Signatures)âYou can give a custom JSON schema and force the AI to answer in this format. The output structure is then consistent and predictable. Use a schema when an automated system reads the output, or when you store the result.
See Structured Output for more information and usage examples.
Config-driven variants (p_config)
Section titled âConfig-driven variants (p_config)âBy default, generate_text reads its configuration from the uc_ai globals and
the provider package globals. This configuration holds the base URL, the
credential, the reasoning level, the tool tags, and the provider-specific
options. Set these globals first, then call generate_text.
The p_config overloads take all of this configuration as one JSON object,
without a change to the globals. They exist for another library or package
that calls UC AI directly and self-contained:
- The call neither reads nor changes the globals. It takes its configuration only
from
p_config. - The call is safe for concurrent and re-entrant use. Each call owns its configuration for its whole duration. A nested call, for example an agent that runs as a tool, cannot disturb it.
- A key that you omit falls back to the framework default, that is the value that
uc_ai.reset_globalsrestores. It does not fall back to the current global value.
p_config takes the same JSON structure as
uc_ai_prompt_profiles_api.apply_model_config.
It holds root-level keys such as g_base_url, g_enable_tools, g_tool_tags,
g_reasoning_level, g_max_tool_calls, g_apex_web_credential, and
g_extra_headers. It also takes an optional nested object with the name of the
provider, for the provider-specific settings. An unknown key raises ORA-20503.
An unknown provider raises ORA-20306.
DECLARE l_config JSON_OBJECT_T; l_result JSON_OBJECT_T;BEGIN l_config := JSON_OBJECT_T('{ "g_enable_tools": true, "g_tool_tags": ["timetracking"], "g_apex_web_credential": "MY_OPENAI_CRED", "openai": { "g_use_responses_api": false, "g_reasoning_effort": "low" } }');
l_result := uc_ai.generate_text( p_user_prompt => 'Clock me in to the marketing project.', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_luna, p_config => l_config );
DBMS_OUTPUT.PUT_LINE(l_result.get_clob('final_message'));END;/For structured output in a config-driven call, pass the schema in
p_response_json_schema. UC AI ignores a response_schema key inside p_config.
The run context
Section titled âThe run contextâp_run_context binds name/value pairs to one call. UC AI adds them to the
arguments of every tool under the reserved key _ctx, so a tool handler can read
a value that the model cannot choose:
l_result := uc_ai.generate_text( p_user_prompt => 'What are the payment terms?', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_sol, p_run_context => json_object_t('{"document_id": "7"}'));Inside an agent run the run context of that run wins. A p_run_context passed to
a nested generate_text call is ignored, so it cannot widen the scope of the run.
The run context describes the whole feature.
Custom HTTP headers
Section titled âCustom HTTP headersâSet uc_ai.g_extra_headers before the call to send extra HTTP headers with every
provider REST request. Examples are a tenant ID, a tracing header, or a header
that an API gateway needs:
BEGIN uc_ai.g_extra_headers('X-Tenant-Id') := 'acme'; uc_ai.g_extra_headers('X-Trace-Id') := 'abc123';
-- next generate_text / generate_embeddings call sends both headersEND;/With the config-driven overloads, pass them as a JSON object under the
g_extra_headers key instead:
{ "g_extra_headers": { "X-Tenant-Id": "acme", "X-Trace-Id": "abc123" } }UC AI appends your headers after its own headers for Content-Type,
authentication, and the provider version. Do not use a name that the framework
already sets. UC AI sends such a header in addition to its own header, and not
instead of it. uc_ai.reset_globals clears g_extra_headers, the same as every
other global.
Custom request-body properties
Section titled âCustom request-body propertiesâSet uc_ai.g_extra_body to a JSON object to send a provider parameter that the
SDK does not wrap. Examples are top_p, stop_sequences, service_tier,
metadata, and the Anthropic cache_control. UC AI merges the top-level keys of
this object into the outgoing request body:
BEGIN uc_ai.g_extra_body := json_object_t('{"top_p": 0.9, "stop_sequences": ["END"]}');
-- next generate_text call adds top_p and stop_sequences to the request bodyEND;/With the config-driven overloads, pass the same object under the g_extra_body
key:
{ "g_extra_body": { "top_p": 0.9, "stop_sequences": ["END"] } }Notes:
- The shape is provider-specific. Write each key exactly as the API of the target provider expects it. A key here overwrites the value of the framework. You can therefore also change a parameter that the SDK sets, for example the Anthropic temperature.
- A nested object replaces the whole object. There is no deep merge.
- The âcoreâ keys that define the conversation are protected:
model,messages,input,instructions,system, andtools. UC AI ignores a value for these keys ing_extra_bodyand writes it to the log. Usep_model,p_messages, andg_provider_toolsfor these values. - For OCI,
g_extra_bodymerges into thechatRequestobject and not into the outer request body. OCI keeps its generation parameters inchatRequest. uc_ai.reset_globalsclearsg_extra_body.
Provider (server-side) tools
Section titled âProvider (server-side) toolsâYou can also enable the server-side tools of a provider, next to the local
PL/SQL tools that you register. The provider
runs these tools, not your database. Examples are Anthropic web search and the
OpenAI Responses API web search. Set uc_ai.g_provider_tools to a JSON array of
provider-native tool definitions. UC AI appends them to the tools array of the
request without a change:
BEGIN -- Anthropic server-side web search uc_ai.g_provider_tools := json_array_t( '[{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}]' );
DECLARE l_result json_object_t; BEGIN l_result := uc_ai.generate_text( p_user_prompt => 'What is the latest stable version of Oracle APEX?' , p_provider => uc_ai.c_provider_anthropic , p_model => uc_ai_anthropic.c_model_claude_4_5_haiku ); END;END;/For the OpenAI Responses API (the default OpenAI path):
{ "g_provider_tools": [ { "type": "web_search_preview" } ] }Notes:
- UC AI passes each definition without a change. You must match the exact schema of the provider, and you must enable the tool in your provider account. The provider documentation gives the details: Anthropic tool use, OpenAI tools.
- UC AI sends provider tools also when local tools are disabled
(
g_enable_tools = false). When you set both, UC AI sends both. - The provider runs these tools and returns the results inline. UC AI never calls
them locally. The result blocks in the response, such as
server_tool_useandweb_search_tool_result, pass through the conversation. They do not count as local tool calls. - UC AI appends a Google server tool, for example
{"googleSearch": {}}, next to the function-declarations entry. The Gemini API expects this position. uc_ai.reset_globalsclearsg_provider_tools.
Return Object Overview
Section titled âReturn Object OverviewâThe uc_ai.generate_text() function returns a JSON_OBJECT_T with information about the AI interaction. This object holds the conversation history, the usage statistics, and metadata about the model and the provider.
Structure
Section titled âStructureâThe return object contains the following properties:
{ "final_message": "The AI's final response text", "messages": [...], -- Complete conversation history (JSON_ARRAY_T) "finish_reason": "stop", -- How the conversation ended (VARCHAR2) "usage": { -- Token usage statistics (JSON_OBJECT_T) "prompt_tokens": 45, -- input tokens used (NUMBER) "completion_tokens": 23, -- output tokens used (NUMBER) "reasoning_tokens": 15 -- amount of output tokens used for reasoning (NUMBER) "total_tokens": 68, -- total tokens used (NUMBER) }, "tool_calls_count": 2, -- Number of tools executed (NUMBER) "model": "gpt-5.6-luna", -- AI model used (VARCHAR2) "provider": "openai" -- AI provider (VARCHAR2)}Three more properties are present only in the conditions that produce them:
block_reason, provider_finish_reason and error_message. The table below
gives the condition for each one.
Properties Reference
Section titled âProperties Referenceâ| Property | Type | Description |
|---|---|---|
final_message | CLOB | The final assistant message from the conversation. With p_response_json_schema it holds the JSON as text |
messages | JSON_ARRAY_T | Complete conversation history including user, system, assistant, and tool messages |
finish_reason | VARCHAR2 | Completion reason: stop, tool_calls, length, content_filter, max_tool_calls_exceeded |
usage | JSON_OBJECT_T | Token usage statistics with prompt_tokens, completion_tokens, and total_tokens |
tool_calls_count | NUMBER | Total number of tool calls executed during the conversation |
model | VARCHAR2 | The AI model used (for example gpt-5.6-luna or claude-sonnet-5) |
provider | VARCHAR2 | AI provider identifier (openai, anthropic, google) |
block_reason | VARCHAR2 | Google only, and only when the provider blocked the prompt. Holds the reason, for example PROHIBITED_CONTENT. finish_reason is content_filter and final_message is null |
provider_finish_reason | VARCHAR2 | Present when the provider ended the run for a reason that maps to no value in the table below. finish_reason is then unknown, and this property holds the providerâs own word |
error_message | VARCHAR2 | OCI Cohere only, and only when the provider reported an error instead of an answer. Holds the message that came with it |
Accessing Return Values
Section titled âAccessing Return ValuesâBasic Usage
Section titled âBasic UsageâDECLARE l_result JSON_OBJECT_T; l_final_response CLOB; l_finish_reason VARCHAR2(255);BEGIN -- Make AI request l_result := uc_ai.generate_text( p_user_prompt => 'What is the weather like in London?', p_system_prompt => 'You are a helpful weather assistant.' );
-- Get the final AI response l_final_response := l_result.get_string('final_message'); DBMS_OUTPUT.PUT_LINE('AI Response: ' || l_final_response);
-- Check how the conversation ended l_finish_reason := l_result.get_string('finish_reason'); DBMS_OUTPUT.PUT_LINE('Finish reason: ' || l_finish_reason);END;/Usage Statistics
Section titled âUsage StatisticsâDECLARE l_result JSON_OBJECT_T; l_usage JSON_OBJECT_T; l_total_tokens NUMBER; l_tool_calls_count NUMBER;BEGIN l_result := uc_ai.generate_text( p_user_prompt => 'Calculate the area of a circle with radius 5', p_max_tool_calls => 3 );
-- Get usage statistics l_usage := l_result.get_object('usage'); l_total_tokens := l_usage.get_number('total_tokens'); l_tool_calls_count := l_result.get_number('tool_calls_count');
DBMS_OUTPUT.PUT_LINE('Tokens used: ' || l_total_tokens); DBMS_OUTPUT.PUT_LINE('Tool calls made: ' || l_tool_calls_count); DBMS_OUTPUT.PUT_LINE('Model: ' || l_result.get_string('model')); DBMS_OUTPUT.PUT_LINE('Provider: ' || l_result.get_string('provider'));END;/Message History
Section titled âMessage HistoryâThe messages array contains the complete conversation history with different message types:
Message Structure
Section titled âMessage Structureâ[ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "What is the weather in London?" }, { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"location\": \"London\"}" } } ] }, { "role": "tool", "tool_call_id": "call_123", "content": "Temperature: 18°C, Condition: Partly cloudy" }, { "role": "assistant", "content": "The current weather in London is 18°C and partly cloudy." }]Processing Message History
Section titled âProcessing Message HistoryâDECLARE l_result JSON_OBJECT_T; l_messages JSON_ARRAY_T; l_message JSON_OBJECT_T; l_role VARCHAR2(100); l_content CLOB;BEGIN l_result := uc_ai.generate_text( p_user_prompt => 'Tell me a joke and then explain why it is funny' );
-- Get the complete message history l_messages := l_result.get_array('messages');
-- Loop through all messages FOR i IN 0 .. l_messages.get_size - 1 LOOP l_message := JSON_OBJECT_T(l_messages.get(i)); l_role := l_message.get_string('role'); l_content := l_message.get_string('content');
DBMS_OUTPUT.PUT_LINE('Role: ' || l_role); DBMS_OUTPUT.PUT_LINE('Content: ' || SUBSTR(l_content, 1, 200)); DBMS_OUTPUT.PUT_LINE('---'); END LOOP;END;/Finish Reasons
Section titled âFinish ReasonsâThe finish_reason indicates how the AI conversation ended:
| Finish Reason | Description |
|---|---|
stop | The model completed its response naturally |
tool_calls | The response ended with tool calls |
length | The maximum token limit truncated the response |
content_filter | The content policy filtered the response |
max_tool_calls_exceeded | The conversation reached the maximum number of tool calls |
unknown | The provider used a reason UC AI does not map. provider_finish_reason holds the original |
A provider can add a reason at any time. A branch on finish_reason therefore
needs an ELSE case. The unknown value keeps a new provider reason from being
read as stop.
Handling Different Finish Reasons
Section titled âHandling Different Finish ReasonsâDECLARE l_result JSON_OBJECT_T; l_finish_reason VARCHAR2(255);BEGIN l_result := uc_ai.generate_text( p_user_prompt => 'Analyze this complex data...', p_max_tool_calls => 5 );
l_finish_reason := l_result.get_string('finish_reason');
CASE l_finish_reason WHEN 'stop' THEN DBMS_OUTPUT.PUT_LINE('Conversation completed successfully');
WHEN 'length' THEN DBMS_OUTPUT.PUT_LINE('Response was truncated due to length limits');
WHEN 'max_tool_calls_exceeded' THEN DBMS_OUTPUT.PUT_LINE('Maximum tool calls reached - consider increasing limit');
WHEN 'content_filter' THEN DBMS_OUTPUT.PUT_LINE('Response was filtered due to content policy');
ELSE DBMS_OUTPUT.PUT_LINE('Unexpected finish reason: ' || l_finish_reason); END CASE;END;/Error Handling
Section titled âError HandlingâIf the AI provider returns an error, or if the request fails, uc_ai.generate_text raises an exception.