tool use as EXPRESS · agents reaching the outside world
OMNIVSThe Silent Failure
OMNI saysAny time an agent touches the outside world — an API, a file, a shell — that is an EXPRESS at the cell tier. Dangerous tools are GATEd, and every result carries an honesty tag.
An agent that only thinks is inert; usefulness comes from reaching out. In molecular terms a tool call is just an EXPRESS — the cell runs its DNA against the world and PRESENTs what came back. The discipline is in the guardrails. Read-only tools (fetch a page, query a DB) are low-risk EXPRESS. Write or destructive tools (POST, delete a file, run a shell) must pass a GATE first: the conductor or a risk worker checks scope and intent before the channel opens. Least privilege from differentiation (mol-62) means most workers simply never hold the dangerous channels.
The other half is honesty. A tool result is real data, so it carries a tag: [ measured ] when the value came back from an actual call, [ stub ] when it is a placeholder standing in for a tool not yet wired, [ honest ] when the agent is being explicit about a limit. This is the same rule the rest of the house follows — never let a stubbed tool masquerade as a measured one, because a swarm that fuses fake results confidently is worse than one that admits it could not reach the tool.
Power-ups you unlock
A tool call is an EXPRESS: the cell runs its DNA against the world
Read-only tools are low-risk; write/destructive tools must pass a GATE first
Least privilege: most workers never hold the dangerous channels (mol-62)
Tool results carry an honesty tag: [ measured ] vs [ stub ] vs [ honest ]
Never let a [ stub ] result fuse as if it were [ measured ]
The Silent Failure attacks — common mistakes
Letting any worker call any tool — no GATE on destructive channels
Returning a placeholder as if it were a real measurement (no honesty tag)
Swallowing a failed tool call and fusing a guess instead of abstaining
Granting broad tool scope for convenience instead of per-role least privilege
Boss battleGive a worker one read tool and one write tool, GATE the write behind a risk check, and tag every result [ measured ] or [ stub ] so the fuse step can tell them apart.
Example code
<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#b388ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
const be = (layer, verb, payload) => ({ layer, verb, payload });
// a worker's allowed channels come from differentiation (least privilege)
function makeWorker(role, canWrite){
return {
read: (url)=> be('cell','EXPRESS', { tag:'[ measured ]', data:'200 OK from ' + url }),
write: (url)=> canWrite
? be('cell','EXPRESS', { tag:'[ measured ]', data:'wrote to ' + url })
: be('cell','GATE', { tag:'[ honest ]', data:'write BLOCKED: ' + role + ' lacks channel' }),
callUnwired: ()=> be('cell','EXPRESS', { tag:'[ stub ]', data:'placeholder — tool not wired' })
};
}
const w = makeWorker('scout', false); // read-only worker
const out = [];
out.push('read → ' + JSON.stringify(w.read('/api/cart').payload));
out.push('write → ' + JSON.stringify(w.write('/api/cart').payload)); // gated
out.push('stub → ' + JSON.stringify(w.callUnwired().payload));
out.push('fuse rule: only [ measured ] results may vote');
document.getElementById('o').textContent = out.join('\n');
</script></body></html>