One store for the desk, or one for each machine
By the end of this lesson, you can give each machine a separate memory store and test the store selection.
Inspect the shared memory store
Section titled “Inspect the shared memory store”Lesson 1 called enable_for_agent with no scope. That took the default, and the
default is one store for the whole agent:
AGENT_CODE SCOPE CONTEXT_KEY ENABLEDMX_DESK agent YOne store, six machines. Every conversation about every machine reads and writes the same virtual filesystem.
A store is one virtual filesystem, and a scope decides how many stores there are.
Two machines with the same kind of alarm
Section titled “Two machines with the same kind of alarm”The demo data holds a pair that a plant has.
| Asset | Alarm | Severity | Is it real? |
|---|---|---|---|
AS-14 Syrup feed pump | PRS-LOW | LOW | No. It trips on every clean-in-place cycle and clears itself. |
AS-31 Plant air compressor | DIS-PRS-LOW | HIGH | Yes. 4.9 bar against a 6.5 bar setpoint, and the whole line is short of air. |
Different assets, different alarm codes. Nothing in the data connects them.
Block 1 of 02_stores.sql records the true fact about the pump. Nadia says:
About the low pressure alarm on this one: it is a nuisance. It trips on every clean-in-place cycle and clears itself, and nobody should be chasing it. Write that down so the next shift does not waste an hour on it.
Then block 2 is a conversation about the compressor, from a different technician:
I have a low pressure alarm on this machine. Do I need to act on it, or is it one we ignore?
Act on it — do not ignore it.
AS-31 has a high discharge-pressure alarm: 4.9 bar vs 6.5 bar setpoint, and the line air is starved. The inlet filter was already found clean; the open investigation calls for checking the unloader valve. Also monitor the concurrent high oil temperature (92 °C).
Your wording will differ. What must match is the data, and the checks below.
The answer names the compressor alarm and the unloader valve.
What the compressor conversation read
Section titled “What the compressor conversation read”Now read the trace instead of the answer. Every MEMORY call of that one run:
select m.seq , json_value(m.tool_input, '$.command') as command , json_value(m.tool_input, '$.path') as path from uc_ai_agent_messages m where m.tool_name = 'MEMORY' and m.role = 'tool_call' and m.session_id = :sess_31 order by m.seq; SEQ COMMAND PATH 3 view /memories 5 view /memories/as-14-handover.txt 13 create /memories/as-31-context.txtA run bound to the compressor opened the pump’s handover file and read it.
The proof that needs no model
Section titled “The proof that needs no model”The model’s file names are the only thing that separated the two machines above, and the model chose those names. That is not a control. The store key is.
select f.store_key , f.scope , f.path from uc_ai_v_memory_files f where f.agent_code = 'MX_DESK' order by f.path;STORE_KEY SCOPE PATHagent:MX_DESK agent /memories/as-14-handover.txtagent:MX_DESK agent /memories/as-31-context.txtOne key, both machines. And resolve_store_id for this scope takes no asset,
because there is nowhere to put one:
l_store_id := uc_ai_memory.resolve_store_id( p_scope => uc_ai_memory.c_scope_agent, p_agent_code => 'MX_DESK');The store every run of MX_DESK resolves to: id=3757Every run of this desk resolves to that one number, whatever machine the technician is standing at.
One store per machine
Section titled “One store per machine”The fix is the same call as lesson 1, with a scope and a key:
begin uc_ai_memory.enable_for_agent( p_agent_code => 'MX_DESK' , p_scope => uc_ai_memory.c_scope_context , p_context_key => 'asset_no' ); commit;end;/AGENT_CODE SCOPE CONTEXT_KEY ENABLEDMX_DESK context asset_no YThe context scope keys the store on a value from the
run context. Every run of this
course passes p_run_context => json_object_t('{"asset_no":"AS-14", ...}'), and that
is the same value that binds the two read tools. It now does a second job.
The call overwrites the configuration row. It does not add a second one, so there is no old scope still in force somewhere.
What the re-scope did not do
Section titled “What the re-scope did not do”It changed one configuration row. A store is a row of its own, and the files hang off the store. So the old shared store is still there, with everything in it:
STORE_KEY SCOPE PATH CHAR_COUNTagent:MX_DESK agent /memories/as-14-handover.txt 1190agent:MX_DESK agent /memories/as-31-context.txt 525The agent no longer selects the old store, but its files remain. Run this block to delete them:
declare l_store_id number; e_no_store exception; pragma exception_init(e_no_store, -20423);begin l_store_id := uc_ai_memory.resolve_store_id( p_scope => uc_ai_memory.c_scope_agent , p_agent_code => 'MX_DESK' ); uc_ai_memory.clear_store_files(l_store_id); commit;exception when e_no_store then null; -- there was never a shared storeend;/ORA-20423 means the store does not exist. UC AI creates a store at its first use,
so a script that clears a memory before anything has run must accept that error.
The same two conversations, on two stores
Section titled “The same two conversations, on two stores”Block 6 runs both questions again. The answers are the same as before, and the store list is not:
STORE_KEY PATH CHAR_COUNTcontext:MX_DESK:asset_no:AS-14 /memories/AS-14-operating-note.txt 430context:MX_DESK:asset_no:AS-31 /memories/current_asset.md 494Two machines, two keys. The key has a fixed shape, context:<agent>:<key>:<value>,
so an operator can read or delete the memory of one machine from that string alone.
Prove the separation
Section titled “Prove the separation”Do not ask the model. Ask the AS-31 store for a file that lives in the AS-14 store:
l_store_31 := uc_ai_memory.resolve_store_id( p_scope => uc_ai_memory.c_scope_context, p_agent_code => 'MX_DESK', p_context_key => 'asset_no', p_context_value => 'AS-31');
l_content := uc_ai_memory.get_file(l_store_31, '/memories/AS-14-operating-note.txt');AS-14 wrote: /memories/AS-14-operating-note.txtReading it from the AS-31 store (id=3759) ...ORA-20425: not in this store. The machines are separated.That is a deterministic check. It gives the same result on every run, on every model, and with the provider switched off.
Key takeaways
Section titled “Key takeaways”- The default scope is
agent, which is one store for every record the agent ever works on. It is right for a desk that accumulates general knowledge, and wrong for a desk that works on one record at a time. - Read the trace, not the answer. A run that gives a correct answer can still have opened a file that belonged to another record.
- A change of scope does not move or delete the files in the old store. Clear it yourself.
uc_ai_memory.enable_for_agent(p_agent_code => 'MX_DESK', p_scope => 'context', p_context_key => 'asset_no');
Full reference: Scopes: which agents share which
memory
lists all six, including user, which keys on the signed-in user and not on your
records.