-- ============================================================ -- 59_kb_select_ai_router_ords.sql -- -- POST /ords/cb-ords/kb-select-ai-agent/run -- Authorization: Bearer -- {"prompt":"...","conversationId":"optional-safe-id"} -- -- The ORDS runtime validates the bearer and sets the application context -- before invoking the POC_2-owned Team API. The context is session scoped, -- so VPD still applies to any SQL action selected by the Select AI tool. -- -- Execute as CB_ORDS after 22 and 58. -- ============================================================ WHENEVER SQLERROR EXIT SQL.SQLCODE SET ECHO OFF SET FEEDBACK ON SET DEFINE OFF PROMPT === Resetting only the KB Select AI Agent ORDS module === BEGIN ORDS.DELETE_MODULE(p_module_name => 'kb.select.ai.agent'); EXCEPTION WHEN OTHERS THEN NULL; END; / PROMPT === Creating KB Select AI Agent ORDS endpoint === BEGIN ORDS.DEFINE_MODULE( p_module_name => 'kb.select.ai.agent', p_base_path => 'kb-select-ai-agent/', p_items_per_page => 0, p_status => 'PUBLISHED' ); ORDS.DEFINE_TEMPLATE( p_module_name => 'kb.select.ai.agent', p_pattern => 'run' ); ORDS.DEFINE_HANDLER( p_module_name => 'kb.select.ai.agent', p_pattern => 'run', p_method => 'POST', p_source_type => ORDS.source_type_plsql, p_source => q'~ DECLARE v_body_text CLOB; v_prompt VARCHAR2(32767); v_requested_conversation_id VARCHAR2(128); v_internal_conversation_id VARCHAR2(128); v_stakeholder_user_id VARCHAR2(4000); v_answer CLOB; BEGIN cb_ords_handler_pkg.set_vpd_context(:auth_header, :probe_id); -- ORDS exposes request JSON as a stream bind. Read it once only. v_body_text := :body_text; v_prompt := JSON_VALUE(v_body_text, '$.prompt' RETURNING VARCHAR2(32767)); v_requested_conversation_id := JSON_VALUE(v_body_text, '$.conversationId' RETURNING VARCHAR2(128)); IF v_prompt IS NULL OR TRIM(v_prompt) IS NULL THEN RAISE_APPLICATION_ERROR(-20801, 'prompt is required'); END IF; IF v_requested_conversation_id IS NULL THEN v_requested_conversation_id := 'kb-' || LOWER(RAWTOHEX(SYS_GUID())); ELSIF NOT REGEXP_LIKE(v_requested_conversation_id, '^[A-Za-z0-9._:-]{1,128}$') THEN RAISE_APPLICATION_ERROR(-20802, 'conversationId contains unsupported characters'); END IF; -- A connection-pooled ORDS session can be reused. Scope the Team's -- conversation memory to the VPD subject as well as the caller's public ID. v_stakeholder_user_id := NVL(SYS_CONTEXT('CB_AGENT_CTX', 'STAKEHOLDER_USER_ID'), 'anonymous'); v_internal_conversation_id := 'kb-' || LOWER(RAWTOHEX(STANDARD_HASH( v_stakeholder_user_id || ':' || v_requested_conversation_id, 'SHA256' ))); v_answer := poc_2.kb_select_ai_router_api.run_team( p_prompt => v_prompt, p_conversation_id => v_internal_conversation_id ); :status_code := 200; OWA_UTIL.MIME_HEADER('application/json', FALSE); HTP.P('Cache-Control: no-store'); OWA_UTIL.HTTP_HEADER_CLOSE; APEX_JSON.OPEN_OBJECT; APEX_JSON.WRITE('team', 'KB_SELECT_AI_ROUTER_TEAM'); APEX_JSON.WRITE('conversationId', v_requested_conversation_id); APEX_JSON.WRITE('answer', v_answer); APEX_JSON.CLOSE_OBJECT; cb_ords_handler_pkg.clear_vpd_context; EXCEPTION WHEN OTHERS THEN cb_ords_handler_pkg.clear_vpd_context; :status_code := CASE WHEN SQLCODE IN (-20801, -20802) OR SQLCODE BETWEEN -40599 AND -40400 THEN 400 WHEN SQLCODE BETWEEN -20199 AND -20100 THEN 403 ELSE 500 END; OWA_UTIL.MIME_HEADER('application/json', FALSE); HTP.P('Cache-Control: no-store'); OWA_UTIL.HTTP_HEADER_CLOSE; APEX_JSON.OPEN_OBJECT; APEX_JSON.WRITE('errorCode', SQLCODE); APEX_JSON.WRITE('error', SQLERRM); APEX_JSON.CLOSE_OBJECT; END; ~', p_items_per_page => 0 ); ORDS.DEFINE_PARAMETER( p_module_name => 'kb.select.ai.agent', p_pattern => 'run', p_method => 'POST', p_name => 'Authorization', p_bind_variable_name => 'auth_header', p_source_type => 'HEADER', p_param_type => 'STRING', p_access_method => 'IN' ); ORDS.DEFINE_PARAMETER( p_module_name => 'kb.select.ai.agent', p_pattern => 'run', p_method => 'POST', p_name => 'X-VPD-Probe-Id', p_bind_variable_name => 'probe_id', p_source_type => 'HEADER', p_param_type => 'STRING', p_access_method => 'IN' ); COMMIT; END; / PROMPT === KB Select AI Agent ORDS endpoint ready === PROMPT Path: /ords/cb-ords/kb-select-ai-agent/run EXIT