Skip to content

Event Callbacks

UC AI can send events to a PL/SQL procedure of your choice during a generate_text call. Use these events for:

  • A streaming-style UI — show the assistant text or the tool call activity at once, and do not wait for the whole answer.
  • Audit logging — record every tool call and its result, for compliance or to find a fault.
  • Observability — group the events of one request id across providers, or across a long agent run.

An event callback is global to the session. Register it once. Every later generate_text call in that session then sends its events to your procedure, until you clear the callback.

Your callback must be a top-level procedure that the schema can see. It must have this exact signature:

procedure my_ai_event_handler(
p_request_id in varchar2
, p_event_type in varchar2
, p_event_data in clob -- JSON serialized payload
);

p_event_data is a CLOB and not a json_object_t, because execute immediate cannot bind a PL/SQL object type. For structured access, parse it with json_object_t.parse(p_event_data).

Register it with:

uc_ai.set_event_callback('MY_SCHEMA.MY_PKG.MY_AI_EVENT_HANDLER');

And clear it with:

uc_ai.clear_event_callback;

uc_ai.reset_globals keeps the registered callback name. You therefore do not register it again in each session.

ConstantEvent typeWhen it fires
uc_ai.c_event_assistant_textassistant_textThe assistant returns a text content block
uc_ai.c_event_assistant_reasoningassistant_reasoningThe assistant returns a reasoning block
uc_ai.c_event_tool_calltool_callBefore a tool runs
uc_ai.c_event_tool_resulttool_resultAfter a tool runs, with its result
uc_ai.c_event_response_completeresponse_completeAt the end of generate_text, with the final result object

Every event is session-scoped. UC AI sets uc_ai.g_request_id at the start of each generate_text call, and clears it at the end. An event outside a generate_text call does not fire. This includes the time when you build the input messages yourself.

This small handler writes each event to dbms_output:

create or replace package my_pkg is
procedure on_ai_event(
p_request_id in varchar2
, p_event_type in varchar2
, p_event_data in clob
);
end my_pkg;
/
create or replace package body my_pkg is
procedure on_ai_event(
p_request_id in varchar2
, p_event_type in varchar2
, p_event_data in clob
)
as
l_data json_object_t;
begin
l_data := json_object_t.parse(p_event_data);
dbms_output.put_line('[' || p_request_id || '] ' || p_event_type);
case p_event_type
when uc_ai.c_event_assistant_text then
dbms_output.put_line(' text: ' || l_data.get_string('text'));
when uc_ai.c_event_tool_call then
dbms_output.put_line(' tool: ' || l_data.get_string('toolName'));
when uc_ai.c_event_tool_result then
dbms_output.put_line(' result: ' || l_data.get_clob('result'));
else
null;
end case;
end on_ai_event;
end my_pkg;
/

Use it:

begin
uc_ai.set_event_callback('MY_PKG.ON_AI_EVENT');
declare
l_result json_object_t;
begin
l_result := uc_ai.generate_text(
p_user_prompt => 'What is the email address of Jim?'
, p_provider => uc_ai.c_provider_openai
, p_model => uc_ai_openai.c_model_gpt_5_6_luna
);
end;
uc_ai.clear_event_callback;
end;
/

The output of a tool-calling path looks like this:

[A1B2C3...] tool_call
tool: TT_GET_USERS
[A1B2C3...] tool_result
result: [{"user_id":4,"first_name":"Jim",...}]
[A1B2C3...] assistant_text
text: jim.halpert@dundermifflin.com
[A1B2C3...] response_complete

If your callback raises an exception, UC AI catches it by default. A broken handler therefore never breaks an AI call. UC AI writes each failure to uc_ai_logger, with a backtrace for the diagnosis.

During development, an error in your handler must be visible. To abort the generate_text call on a callback error, set:

uc_ai.g_callback_fatal := true;

uc_ai.reset_globals resets g_callback_fatal, but it does not reset g_event_callback.

p_request_id is a correlation id for one call, as a hex GUID. Two sequential generate_text calls get two different request ids. Use this id to group the events of one AI call when several calls run in the same session, for example inside a multi-agent workflow.

During a call, you can also read the current request id from uc_ai.g_request_id.

set_event_callback validates the procedure name with dbms_assert.qualified_sql_name. A malformed name such as not a valid name!!! therefore raises ORA-44003 or ORA-44004 before the first event.