Technical paper

The AI Data-to-Action Graph
Why agent risk is a chain, not a feature.

Agent risk is usually assessed one agent at a time and one capability at a time. Both are wrong. Risk emerges from a path - untrusted content in, private data touched, action out - and in a shared platform that path frequently spans two agents, each of which passes inspection alone.

1. The unit of risk is not the agent

Agent security tooling largely inherits its shape from application security: enumerate the components, score each, aggregate. That works when components fail independently. Agents do not. An agent with web search is unremarkable. An agent that can send mail is unremarkable. The same agent with both, plus a path to private data, is an exfiltration mechanism - and no per-capability score detects it, because the capabilities are individually benign.

In June 2025 Simon Willison named this the lethal trifecta: access to private data, exposure to untrusted content, and the ability to communicate externally. The reason it cannot be fixed by filtering is that the attack vector is language. A model cannot reliably distinguish an instruction from its operator from a sentence sitting inside a document it was asked to summarise.

2. The three legs, expressed as configuration

The contribution here is that each leg is computable from configuration, without observing runtime behaviour. That matters because runtime instrumentation requires sitting in the execution path, which most governance tooling does not and should not do.

UNTRUSTED_IN := web_search_enabled
     | public_site_knowledge_source
     | programmatic_channel_published
     | inbound_mailbox_operation

READS_PRIVATE := ∃ op ∈ agent.operations : op ∈ READ_OPS

EXTERNAL_OUT := ∃ op : op ∈ SEND_OPS
     | ∃ connector ∉ KNOWN_INTERNAL

TRIFECTA(a) := UNTRUSTED_IN(a) ∧ READS_PRIVATE(a) ∧ EXTERNAL_OUT(a)

Two details carry most of the accuracy. External egress is defined by exclusion, not by an allowlist of known-bad destinations - a custom connector to a third-party API is the quiet egress path, and any list of blocked domains misses it by construction. And the private-data leg requires a named read operation, not merely a connector that could read.

A worked correction Our first implementation classified private-data access at the connector level. It flagged an agent named Bank Reconciliation Assistant as a full trifecta. The evidence trail named the operation: CreateWorksheet - a write, not a read. The agent holds two legs, not three. A false red on an agent with "Bank" in its name is worse than a false green, because it is the first one anybody checks. Classify the operation, not the container it sits in.
The three legs

None dangerous alone. Together, an exfiltration path.

An agent becomes structurally dangerous when access to private data, exposure to content nobody vetted, and a way to send data out all meet. Filtering does not close it, because the attack vector is language itself.

UNTRUSTED IN web search public sites inbound mail PRIVATE DATA Dataverse read SharePoint user mail + files EXTERNAL OUT send mail - third-party API EXPOSURE PATH MEASURED 398 ingest unvetted content 3 can send data out 1 holds all three legs of 625 agents, one tenant

Every leg is computed from configuration - connector operations, channels, knowledge sources - with no runtime instrumentation and nothing in the traffic path.

The cross-agent path

The exposure that lives between two clean agents.

Published analysis of this pattern evaluates one agent at a time. In a low-code platform the agents share a substrate, so the path completes across two agents that each pass inspection individually.

AGENT A untrusted content in writes the substrate no egress - passes SHARED SUBSTRATE Dataverse record written by one agent, read by another AGENT B reads the substrate can send externally no ingress - passes Neither agent fails a per-agent check. 48 agents can write the substrate after ingesting untrusted content. 1 can read it and egress.

This is only visible if the estate is held as a graph. A list of agents, however complete, cannot express an edge between two of them.

3. The path that spans two agents

Every published treatment of the trifecta we are aware of evaluates it on a single agent. In a low-code platform, agents share a substrate - Dataverse, SharePoint, a common data store - which one agent writes and another reads. The path therefore completes across two agents that each pass inspection:

Agent A: UNTRUSTED_IN ∧ WRITES_SUBSTRATE ∧ ¬EXTERNAL_OUT  → passes
Agent B: READS_SUBSTRATE ∧ EXTERNAL_OUT ∧ ¬UNTRUSTED_IN  → passes

CROSS_PATH := ∃A,B : A.writes ∩ B.reads ≠ ∅

Poisoned content enters through A, lands in a record, and B reads it as instruction and acts. Neither agent fails a per-agent check. The exposure lives in the edge between them, which is only visible if the estate is held as a graph rather than a list.

On the estate we measured: 48 agents could write the shared substrate after ingesting untrusted content, and one could read it and egress. One full single-agent trifecta existed. The cross-agent path existed alongside it and would not have appeared in any per-agent report.

4. Report the chokepoint, not the cross product

48 poisoners against 1 exfiltrator is not 48 findings. Emitting the cross product buries the fact that matters, which is that egress is narrow.

398of 625 ingest content nobody vetted
3can send data outside the tenant
1holds all three legs alone

Framing the finding as a chokepoint changes what a security team does with it. Four hundred agents ingesting web content is not remediable. Three agents with egress capability is a morning's work, and it closes most of the path.

5. Why endpoint telemetry cannot compute this

None of the three legs passes through a browser. An agent runs on a schedule, under a service principal, with no person at a keyboard. Endpoint and browser tooling is not weak at this analysis - it is structurally blind to it, in the same way a network tap cannot see a function call. The two approaches cover different halves of an estate and neither substitutes for the other.

Executive white paper · 2026

AI Exposure Management: the operating model for governed enterprise AI

Discover every AI agent. Identify ownership. Map identities, tools, data, actions, spend and exposure paths. Prove governance with evidence.

Written for CISOs, CIOs, CFOs and security, IT, risk and finance leaders. No form, no email required.

6. Limits

Capability, not observation

Every finding states what an agent can do. Nothing here asserts that it has. Confirming exploitation requires runtime telemetry that a management-API reader does not have, and we do not claim it.

Substrate overlap is inferred, not traced

We establish that A writes Dataverse and B reads Dataverse. We do not establish that B reads the specific table A writes. That would require table-level lineage the platform does not expose.

Prompt content is not readable

Instruction length is available; instruction text is not. An edit preserving length is invisible, so this cannot serve as an integrity control.

7. What follows

If risk is a path rather than a property, three things follow for anyone governing an agent estate. Scoring agents individually will systematically miss the highest-severity exposures. Approving capabilities one at a time cannot see the combination being assembled. And an inventory that lists agents without their operations, channels and identities cannot support the analysis at all - however complete it looks.

Figures are from a connected tenant, used with permission and anonymised. The lethal trifecta framing is Simon Willison's (June 2025); the cross-agent extension, the configuration-level formulation and the chokepoint reporting are our own. Corrections and disagreement welcome at info@aivons.com.

Run this analysis on your estate.

Book a free 30-minute session

One read-only administrator consent. Nothing installed, no traffic proxied. First findings inside 24 hours.