Profile Agents
A profile agent runs a prompt profile on each call.
A profile agent gives the same AI answer as a direct call to uc_ai_prompt_profiles_api.execute_profile. The difference is the work around the call:
- Execution tracking: UC AI logs every call in the
uc_ai_agent_executionstable, with the status, the token counts, and the timing. This log is your audit trail, and it makes a fault easier to find. - Session grouping: use a session ID to group related agent calls. You can then trace a whole multi-step process as one unit.
- Composability: a workflow, an orchestrator, and a conversation can all reference a profile agent. Profile agents are the building blocks of every other pattern.
Creating a profile agent
Section titled âCreating a profile agentâFirst, create a prompt profile (or use an existing one):
DECLARE l_profile_id NUMBER;BEGIN l_profile_id := uc_ai_prompt_profiles_api.create_prompt_profile( p_code => 'GEO_ASSISTANT', p_description => 'Answers geography questions', p_system_prompt_template => 'You are a geography assistant. Answer in one short sentence.', p_user_prompt_template => '{question}', p_provider => uc_ai.c_provider_openai, p_model => uc_ai_openai.c_model_gpt_5_6_luna, p_status => uc_ai_prompt_profiles_api.c_status_active );
COMMIT;END;/Then wrap it in an agent:
DECLARE l_agent_id NUMBER;BEGIN l_agent_id := uc_ai_agents_api.create_agent( p_code => 'geo_agent', p_description => 'Answers geography questions in one sentence', p_agent_type => uc_ai_agents_api.c_type_profile, p_prompt_profile_code => 'GEO_ASSISTANT', p_status => uc_ai_agents_api.c_status_active );
COMMIT; -- agents must be committed before they can be executedEND;/Executing a profile agent
Section titled âExecuting a profile agentâDECLARE l_result json_object_t; l_params json_object_t := json_object_t(); l_session_id VARCHAR2(100);BEGIN l_session_id := uc_ai_agents_api.generate_session_id; l_params.put('question', 'What is the capital of France?');
l_result := uc_ai_agents_api.execute_agent( p_agent_code => 'geo_agent', p_input_parameters => l_params, p_session_id => l_session_id );
DBMS_OUTPUT.PUT_LINE('Answer: ' || l_result.get_clob('final_message'));END;/UC AI passes p_input_parameters as the prompt profile parameters. Each key maps to a {placeholder} in the profile templates.
Attaching files (documents & images)
Section titled âAttaching files (documents & images)âA profile agent and an orchestrator agent can also take files next to the text
input, through the p_files parameter. Files include a PDF and an image. UC AI
attaches each file to the user message, so the model can analyze it in the same
call. Build the collection with uc_ai_message_api.t_files. The model must be
multimodal (see file analysis).
DECLARE l_result json_object_t; l_files uc_ai_message_api.t_files := uc_ai_message_api.t_files();BEGIN l_files.extend; l_files(1).media_type := 'application/pdf'; l_files(1).data_blob := (SELECT blob_content FROM my_docs WHERE id = 1); l_files(1).filename := 'report.pdf';
l_result := uc_ai_agents_api.execute_agent( p_agent_code => 'doc_agent', p_input_parameters => json_object_t('{"question": "Summarize the attached report."}'), p_files => l_files );
DBMS_OUTPUT.PUT_LINE(l_result.get_clob('final_message'));END;/p_files also works with p_follow_up_message, to attach a file to a follow-up
turn. Only a profile agent and an orchestrator agent support it. A file
for a workflow agent or a handoff agent raises an error.
Execution tracking
Section titled âExecution trackingâEvery call to execute_agent creates a row in uc_ai_agent_executions. Query this table to see what happened:
SELECT ae.id, a.code AS agent_code, ae.status, ae.created_by, ae.total_input_tokens, ae.total_output_tokens, ae.started_at, ae.completed_at FROM uc_ai_agent_executions ae JOIN uc_ai_agents a ON a.id = ae.agent_id WHERE ae.session_id = :session_id ORDER BY ae.started_at;Each row also holds the environment of the caller: created_by, the database user, the APEX user, session, app, and page, the module, and a full env_context JSON snapshot. Session tracking describes these columns.
A workflow with three profile agent steps writes three execution rows under one session. You can then see which step used the most tokens, or which step failed.
Message log at a glance
Section titled âMessage log at a glanceâA profile agent calls the model directly. Its turn therefore writes the most detailed uc_ai_agent_messages transcript: the user prompt, the reasoning, tool_call, and tool_result rows, and the assistant answer. On every agent row, agent_code names the profile agent.
| seq | role | agent_code | tool_name | content |
|---|---|---|---|---|
| 1 | user | (null) | What's the weather in NYC? | |
| 2 | tool_call | weather_agent | get_weather | |
| 3 | tool_result | weather_agent | get_weather | {"tempC":18,"sky":"clear"} |
| 4 | assistant | weather_agent | It's 18 C and clear in NYC. |
On a follow-up turn, UC AI appends only the new messages of that turn, and continues the seq of the session. An earlier turn keeps its own rows.
Profile agents as building blocks
Section titled âProfile agents as building blocksâEvery workflow step, every orchestrator delegate, and every conversation participant is a profile agent.
For example, a sequential workflow references profile agents by their agent code:
{ "workflow_type": "sequential", "steps": [ { "agent_code": "geo_agent", "input_mapping": { "question": "{$.input.question}" }, "output_key": "geo_result" }, { "agent_code": "summarizer_agent", "input_mapping": { "text": "{$.steps.geo_result}" }, "output_key": "summary" } ]}An orchestrator lists them as delegates that the AI can call as tools:
{ "delegate_agents": ["geo_agent", "math_agent", "history_agent"]}And conversations list them as participants:
{ "agents": [ { "agent_code": "brainstormer_agent", "input_mapping": { ... } }, { "agent_code": "critic_agent", "input_mapping": { ... } } ]}In every pattern, UC AI tracks each profile agent run separately. You therefore see every AI call in the chain.
Conversation continuation
Section titled âConversation continuationâA profile agent supports a multi-turn conversation across several execute_agent calls. A follow-up message builds on the earlier conversation, so the calls are not independent.
How it works
Section titled âHow it worksâ- On the first call, the agent runs its prompt profile as usual, with the system prompt and the user prompt from the templates. UC AI stores the full conversation in the execution result, with every tool call exchange.
- On a follow-up call, pass
p_follow_up_messagewith the samep_session_id. UC AI loads the earlier conversation messages, appends your new message, and sends the full history to the LLM.
DECLARE l_result json_object_t; l_session_id VARCHAR2(100);BEGIN l_session_id := uc_ai_agents_api.generate_session_id;
-- First call: uses prompt profile template substitution as usual l_result := uc_ai_agents_api.execute_agent( p_agent_code => 'geo_agent', p_input_parameters => json_object_t('{"question": "What are the 5 largest cities in Europe?"}'), p_session_id => l_session_id );
DBMS_OUTPUT.PUT_LINE(l_result.get_clob('final_message'));
-- Follow-up: the LLM sees the full previous conversation l_result := uc_ai_agents_api.execute_agent( p_agent_code => 'geo_agent', p_follow_up_message => 'Which of those have the best public transport?', p_session_id => l_session_id );
DBMS_OUTPUT.PUT_LINE(l_result.get_clob('final_message'));
-- Another follow-up l_result := uc_ai_agents_api.execute_agent( p_agent_code => 'geo_agent', p_follow_up_message => 'Compare the top 2 in more detail.', p_session_id => l_session_id );
DBMS_OUTPUT.PUT_LINE(l_result.get_clob('final_message'));END;/Each follow-up call creates its own execution row in uc_ai_agent_executions. The same session_id links all of these rows.
History management
Section titled âHistory managementâA long conversation sends much history to the LLM. To control the token usage, set p_max_history_messages at the creation of the agent. The agent then uses a sliding window:
DECLARE l_agent_id NUMBER;BEGIN l_agent_id := uc_ai_agents_api.create_agent( p_code => 'chat_agent', p_description => 'A conversational assistant', p_agent_type => uc_ai_agents_api.c_type_profile, p_prompt_profile_code => 'CHAT_PROFILE', p_max_history_messages => 20, p_status => uc_ai_agents_api.c_status_active );END;/When the history passes the limit of p_max_history_messages, UC AI keeps the system message, which is the first message, and the most recent N messages.
When to use profile agents directly
Section titled âWhen to use profile agents directlyâA workflow or a conversation is not always necessary. Use a profile agent alone when:
- You have a single AI task, and you want execution tracking for the token usage, the timing, and the success or failure
- You want to adopt the agent framework step by step. Start with a wrapper around an existing prompt profile, and compose the agents later
- You need a consistent API in your application.
execute_agentworks the same for every agent type, so a later change from a profile agent to a workflow needs no change in the calling code