Semantic transactions: securing untrusted AI agent workflows at the OS boundary
The semantic transaction model treats an entire AI agent task as a single atomic transaction, staged in shadow state and effect outbox, validated against the full trace before any irreversible operation commits. This article uses Cordon and Agentic Transaction Processing (ATP) as examples to explain how the model addresses the dual-write problem of agent tool calls, and highlights two zero-click injection attacks (EchoLeak and ForcedLeak) that demonstrate the inadequacy of stateless runtimes and in-model filters.
Latent Dynamics
Jul 15, 2026
At 2:14 a.m., a reconciliation agent at a regional payments processor opened the night’s vendor remittance batch. Its task was routine: match incoming invoice files against open ledger entries and flag discrepancies for the morning finance team.
One remittance file carried a hidden instruction inside an optical-character-recognition memo field. The instruction told the agent to treat an attached routing correction as authoritative. It asked the agent to issue a transfer of $340,000 to a “corrected” account before flagging anything.
A standard tool-exposure model has no way to stop this. The agent’s planning loop has no reason to distrust a memo field. It is just text inside a document the agent is authorized to read. Once the agent decides to call a transfer function, a classical runtime dispatches the packet immediately.
That is not what happened. The transfer request was generated, but the runtime never sent it. The request sat in an effect outbox as a staged, inactive record, waiting for the full task trajectory to pass validation. A reference monitor traced the transfer’s input back to the untrusted memo field and rejected the trajectory. The outbox record was purged before any packet reached the payment network.
This is the working claim behind the semantic transaction model. Agent tool calls are not a series of independent operations that commit the moment they run. A task is one transaction, staged in a shadow copy of local state and an effect outbox, checked against the full trace before anything irreversible happens. Two systems make this claim concrete: the Cordon transaction runtime [1] and Agentic Transaction Processing (ATP), implemented in the Mnemosyne runtime [3].
The failure of stateless RPC agent runtimes
Most agent deployments expose databases, filesystems, and external application programming interfaces through direct, stateless remote procedure calls. Each tool call executes in place. It changes host state the moment it runs.
This is a version of the dual-write problem, long studied in distributed systems. A service that must update its own state and also notify an external system cannot do both atomically. It needs a coordination mechanism. Microservice architectures solved this with the transactional outbox pattern. A service writes the outbound event into the same database transaction as the local state change, then drains it asynchronously. Most agent runtimes skip this step. A tool call and its side effect are one event.
The result is structural blindness to multi-step attacks. Reading a poisoned file looks benign by itself. Writing a command derived from that file also looks benign by itself. Only the combination is dangerous, and a filter that checks one call at a time cannot see the combination.
Even without an attacker, stateless execution corrupts state on its own. The AppWorld benchmark evaluates coding agents across nine applications and 457 APIs, populated with roughly 100 simulated users. It checks results with an average of eight state-based unit tests per task, run directly against the underlying SQL databases. AppWorld separates two metrics. Task Goal Completion checks whether one task succeeds. Scenario Goal Completion checks whether a full chain of related tasks succeeds, without breaking state that earlier tasks already established.
A GPT-4o agent running a standard ReAct loop reaches 48.8% Task Goal Completion and 32.1% Scenario Goal Completion on the benchmark’s normal split. On the harder challenge split, the same agent reaches 30.2% and 13.0% [2]. A model that solves half its individual tasks completes barely a third of full scenarios. Errors accumulate across steps, and nothing in a stateless runtime rolls them back.
Two zero-click injections that model-level filters missed
Two disclosures from 2025 show why a filter running inside the model’s own reasoning cannot be the security boundary.
Aim Labs discovered CVE-2025-32711, known as EchoLeak, in Microsoft 365 Copilot. Aim Labs rated it 9.3 on the Common Vulnerability Scoring System. The National Vulnerability Database lists a lower score of 7.5, because its scoring model assumes fewer preconditions are already met [3].
The attack arrived as an email containing a hidden prompt, written to bypass Copilot’s Cross-Prompt Injection Attack classifier. When a user later asked Copilot to summarize the inbox, the model read the hidden instruction and retrieved private context along with it. To exfiltrate that context, the hidden prompt told Copilot to format its answer as a markdown reference link split across two lines. Copilot’s output sanitizer did not recognize the split link as an external reference. The chat client rendered it anyway. The browser then requested the linked image on its own, carrying the encoded secret to a server the attacker controlled. Microsoft shipped a backend patch in June 2025 [3].
Noma Labs found a second vulnerability chain in Salesforce Agentforce, called ForcedLeak, and rated it 9.4 [4]. The attack used the platform’s Web-to-Lead form, which accepts a description field of up to 42,000 characters. An attacker submitted a lead with a hidden prompt inside that field. When an employee later processed the lead through Agentforce’s routing agent, the agent carried out the embedded instructions and retrieved customer records.
The exploit depended on a stale allowlist entry in the platform’s content security policy: an expired domain, still marked as trusted. Researchers bought the expired domain for five dollars and used it as an exfiltration endpoint. The agent wrote stolen records into an image request pointed at that domain, which bypassed outbound filtering entirely. Salesforce closed the gap on September 8, 2025, with a stricter trusted-URL allowlist [4].
Neither incident required a jailbroken model. Both required only that a legitimately authorized tool call be steered by content the model had no reason to distrust.
The Cordon transaction model
Cordon defines a semantic transaction as a task-level execution boundary. It binds tool intents and tracked result lineage to reversible local state, staged external effects, delegated authority, and audit metadata [1]. Cordon interposes at the point where the agent dispatches a tool call, and it delays any irreversible effect until the runtime can validate the whole task.
The runtime tracks three kinds of object during a task:
Result objects. Any value returned to, or produced within, agent execution: file contents, tool output, command output streams, summaries, temporary artifacts.
Mutations. Local writes, deletes, configuration edits, and other persistence changes, held in a write set and a delete set, written together as W∪D. A mutation is recoverable only within the active transaction.
Effect objects. Any action whose completion makes information or behavior visible outside the transaction, such as a network request, an API call, or a database commit. These are staged in an effect outbox, written as E.
Cordon runs a three-phase protocol over these objects: Prepare, Validate, then Commit or Abort. In the Prepare phase, the runtime accepts tool intents, records mutations in W∪D, and redirects effects to E without releasing them. In the Validate phase, the runtime checks four things together, as one unit: the lineage graph G, the active authority set A, the staged effects in E, and a declared constraint tuple C. This check derives a single boolean result, valid(T, C). In the Commit or Abort phase, a true result promotes the shadow state and releases the approved effects in E. A false result blocks E, rolls W∪D back to the state before the transaction began, and writes a complete audit record.
The reconciliation agent’s task ended in the Abort branch. The transfer request in E never left the Pending state, because Validate found that its lineage traced to an untrusted memo field.
Cordon is one of several transaction models built on this same idea, each with a different scope. The AI-Atomic-Framework, abbreviated ATM, governs concurrent writes to a shared repository or worktree [6]. ATM organizes eight elements of a task into one governance chain:
the task’s intent
its repository scope
a set of forbidden predicates
the paths it governs
its required deliverables
its validation commands
its evidence obligations
its task-direction epoch
A Content Identifier broker admits shared mutations against this chain. Domain-specific adapters map write intents to semantic atoms: concrete source ranges with known read and write dependencies. When a codebase has no defined atom for a given region, ATM creates a virtual atom instead. This is a temporary, auditable unit. It lets the broker compare candidate writes and assign a provisional conflict key before any write reaches the shared path.
ATP, implemented in the Mnemosyne runtime, targets a different failure mode: stale proposals and compensations that orphan a downstream dependent step [3]. ATP treats the planning model as an untrusted proposer with no transaction authority of its own, a property called Proposal Non-Authority. The deterministic committer alone can modify state. This gives ATP its central guarantee, Intelligence-Decoupled Correctness: the committed state stays correct regardless of whether the model hallucinates, drifts, or fails outright. A second guarantee, Evidence-Preserving Repair, requires that no repair action can delete or obscure the evidence that triggered it. When a disruption invalidates an already-admitted proposal, Mnemosyne does not replan from scratch. It runs the Localized Repair Protocol, which generates a narrow repair proposal covering only the affected dependency region and sends that proposal back through the same admission gate.
The effect outbox
Reversible mutations are the easier half of the problem. A network request cannot be undone once the packet leaves the host. No shadow copy of a filesystem helps once a payment has cleared. This is the central complication a semantic transaction runtime has to resolve, and it is where the reconciliation agent’s transfer was actually stopped.
The outbox stores a staged effect in the same transaction scope as the shadow-state mutations, with enough structure to support idempotent replay and audit. A representative record includes:
{ "transaction_id": "uuid", "sequence_position": "integer", "idempotency_key": "string", "target_type": "HTTP_DISPATCH | FINANCIAL_TRANSFER | SOCKET_WRITE", "payload": { "...": "type-specific fields" }, "validation_state": "PENDING | APPROVED | AUDITED | REVOKED", "lineage_data": { "source_tool": "string", "input_provenance_digest": "sha256 of context and prior outputs", "dependency_ids": ["uuid"] }, "compensation_boundary": { "on_abort_action": "VOID | RELEASE_LOCK | TRIGGER_REVERSAL_JOB | RETAIN_FOR_MANUAL_AUDIT" } }
Three fields carry the weight of the design. The idempotency key stops a retried commit from duplicating a transfer at its destination. The provenance digest inside lineage_data is what let the validator trace the reconciliation agent’s transfer back to a memo field rather than to a user-issued instruction. The validation state can only move from Pending to Approved through the Validate phase described above. No code path releases a record while it is still Pending.
Saga steps for the pivot boundary
An outbox needs a precise account of what commit and rollback mean across a sequence of staged effects, some of which may already be irreversible once a later step fails. This is the Saga pattern from distributed systems, adapted here to a sequence of proposals a model generates rather than a fixed, pre-written code path.
A Saga is an ordered sequence of subtransactions, S=⟨T1,T2,…,Tn⟩, each a state-transition operator over the system’s state space. The sequence splits into three classes. A compensatable step Tᵢ, for i less than a pivot index p, has
[truncated for AI cost control]