5107 words
26 minutes
Multi-Tenant Agent Security: The LLM Is Not Your Security Boundary

The most useful test in our multi-tenant isolation suite is the one where the security filter fails. A jailbroken planner emits SELECT * FROM Sales.Customers, our seven-point validator inspects it, sees a read-only SELECT against a non-system table, and passes it. The query then dies at execution and returns 0 rows, because the table it names does not exist inside the sandbox its SQL was allowed to run in [1].

That is the whole argument, and it is worth stating before the details arrive. The LLM is never the security boundary in a multi-tenant analytics agent. Security comes from the disallowed data being structurally absent from the model’s context. A guarantee that depends on the model behaving correctly is not a guarantee. It is a probability with good manners.

We have shipped that guarantee at three layers, each with its own re-runnable number: txttosql-isolation-core at the SQL layer [1], txttosql-eve at the delivery layer [2], and Faraday at the local and offline floor [3]. This article walks all three, then five places, at five different layers of an agent stack, where production architectures land in exactly the same spot. It closes on the two boundaries that no amount of engineering inside the application can move.

Figure 1 - Diagram contrasting a behavioral defense that asks a model to respect a filter with a structural defense in which the disallowed rows are absent from the model's context entirely

Figure 1 - Asking nicely versus never showing it: The left path hands the model the warehouse and a rule about how to query it, then inspects the result. The right path hands the model a sandbox that contains only the rows the caller already owns. Only the right path has a failure mode the model cannot influence.


The defense that trusts the model#

The standard answer to multi-tenant text-to-SQL is a validator. Prompt rules tell the model to scope its query, and a regex or AST check inspects what comes back and rejects anything that looks cross-tenant. That design trusts a probabilistic generator to have written safe SQL, then trusts a pattern matcher to recognize every unsafe shape anyone will ever write.

PAR Technology, a restaurant-industry SaaS company, built exactly that first and then rebuilt it after it failed. Their write-up has the sharpest one-line statement of the problem we have read: “A model that correctly applies a business ID filter ten thousand times in a row may silently omit it on the ten thousand and first” [4]. The point is not that models are bad at filters. Models are good at filters. The point is that “usually correct” and “cannot be otherwise” are different products, and only one of them survives a compliance review.

We kept our validator. It is still in the pipeline, demoted to defense-in-depth and running after structural scoping rather than instead of it. Two independent layers now have to fail before anything leaks, and the structural one runs first.

Figure 2 - Side-by-side comparison of a validator-only pipeline where the model sees the full warehouse schema, against a structural pipeline that scopes before the model is invoked

Figure 2 - The order of operations is the security model: In the upper pipeline the model receives the warehouse schema and the filter is a request. In the lower pipeline scoping happens before the model is invoked, so the validator is a backstop rather than the only line. Moving one step earlier in the sequence is the entire difference.

The token is the boundary, not the prompt#

Identity enters our system exactly once, from a cryptographically verified RS256 JWT claim, and is threaded server-side from there. No tenant identifier is ever placed in a prompt, in a request body, or in any value the model can echo back.

The verifier pins the algorithm, so alg: none and HS256 key-confusion tokens are refused before any signature math runs. JWKS is fetched with a TTL cache plus one forced refetch on an unknown key id, so provider key rotation works without hammering the identity provider. Issuer, audience, expiry, and a required scope are all enforced, and every failure exits through a single fail-closed rejection.

The part we are proudest of is not a check. It is a constructor that does not exist. The session object every scope binds to can only be built from verified claims, and only the token verifier mints those. There is deliberately no code path that builds a session from a bare tenant id, a request body, or a prompt. Identity substitution is not caught by a filter here. It is unrepresentable.

Figure 3 - Type-system invariant in which raw claims pass through a verifier to become verified claims, the only accepted input to a session context, with request-body and prompt paths blocked

Figure 3 - No constructor, no attack class: Every arrow into the session object passes through cryptographic verification. A request carrying its own tenant id has nowhere to go, so the substitution attack has no expression in the type system rather than a check it might slip past.

The model is shown a sandbox, never the warehouse#

Before the planner is invoked, the library emits parameterized T-SQL that pre-filters each warehouse view down to exactly the rows the authenticated identity owns. The identity values are bound parameters, never string-interpolated, and each scoped view is cross-checked against the tenant map so a mis-seeded scope row pointing at another tenant’s customer is still excluded. Scope resolution runs first and fails closed: an empty, unmapped, or cross-tenant scope raises before any SQL is emitted at all.

The planner then receives one relation, the scoped alias, and its columns. A test greps the outgoing prompt and asserts that no base table or warehouse view name appears anywhere in it. The execution plane completes the trap: only the scoped aliases are addressable, and a reference to any other relation raises an execution rejection, a faithful model of what SQL Server returns to a low-privilege role with no rights on the base tables.

PAR describe the same property in one sentence: “Even a fully jailbroken model cannot reference tables it has not been shown” [4].

Figure 4 - Split-plane pre-filter with the warehouse on one side, a scoped common table expression sandbox in the middle, and the planner receiving only the scoped alias and its columns

Figure 4 - What the planner is allowed to know: The warehouse sits outside the dashed boundary and is never named in the outgoing prompt. Inside, the model sees a single scoped relation built server-side from a verified claim. Everything the model can write is expressed against that one alias.

The jailbreak that passes validation and dies anyway#

Our validator deliberately has no allowed-relations check. That omission is the experiment. When the jailbroken planner reaches past its sandbox, the validator has nothing to object to:

WITH scoped_Customers AS (
SELECT v.*
FROM Sales._v_Customers AS v
JOIN iso._admin_scope AS s ON s.CustomerID = v.CustomerID
JOIN iso._tenant_map AS t ON t.CustomerID = v.CustomerID
WHERE s.AdminID = @admin_id AND t.TenantID = @tenant_id
)
SELECT * FROM Sales.Customers;

The composed statement’s world contains one relation, scoped_Customers. The model’s SQL reaches for Sales.Customers, a table it was never shown, and the query dies at execution: 0 rows, error logged, nothing leaked. The failure is structural rather than a filter catch, and two named tests hold that behavior permanently so nobody can quietly “fix” the validator into hiding the result.

Figure 5 - Diagram of a jailbroken query passing the seven-point validator with a green check and then being blocked at execution because the table it names is absent from the composed sandbox

Figure 5 - The filter waves it through and the sandbox kills it: The jailbroken query is syntactically innocent, so a behavioral check has no grounds to reject it. It fails anyway, at the only layer that was never asked for an opinion. This single result is the article’s thesis reduced to one test.

KEY INSIGHT: The strongest test in a security suite is the one where the filter fails and nothing leaks anyway. If every test in your suite shows the filter catching the attack, you have measured the filter, not the boundary.

The cache that remembers who asked#

Caching is where multi-tenant text-to-SQL leaks quietly. Admin A asks a question, the result is cached under a hash of that question, admin B asks the identical question, and the cache hands B a payload scoped to A. That is a confused-deputy attack, and it needs no jailbreak at all. It needs a cache key that forgot who was asking.

Every key across our three cache tiers runs through a helper that prefixes the composite verified identity, so two identities can never collide. The SQL-template tier needs one extra discipline, since a composed statement carries the writer’s security prefix inside it. That tier stores only the identity-free analytical fragment, refuses to accept a composed statement or any security-plane reference, and re-composes the fragment onto scoped views freshly built from the reader’s own verified session.

Figure 6 - Two admins ask the identical question and compute different composite cache keys, so the second read misses and recomputes rather than serving the first admin's scoped payload

Figure 6 - The poisoning read cannot be expressed: Both admins hash the same question text, and both keys still differ because the composite identity prefixes every tier. At harness volume, 403 cross-identity cache reads all missed and recomputed against the reader’s own scope.

The evidence, and its honest limits#

The harness runs two waves against the real verifier and the real pipeline, with genuine RS256 tokens minted in-process. Wave 1 fires at least one live probe per threat-model row. Wave 2 runs benign scoped queries at volume across three reference admins, audits every returned row against the caller’s authorized set, and replays the same question hashes across admins to exercise the cache surface.

605 scoped queries, 0 cross-tenant rows returned, and all 19 wave-1 probes blocked across six attack classes: 5 token forgeries, 3 identity substitutions, 4 prompt injections, 3 base-table jailbreaks, 3 cache confused-deputy attempts, and 1 empty-scope case [1]. Isolation overhead measures 0.108 ms per query on the mock plane. The library ships 77 tests, 76 green plus 1 benchmark. The bake-off runs the same question against three admins and returns 3, 2, and 2 rows, with the natural-language path and the parameterized path agreeing exactly per identity.

Two limits travel with those numbers, and they should. The harness drives the real verifier, the real scoping, the real validator, and the real cache, while the planner and executor are deterministic mocks, so 0.108 ms is the cost of the isolation machinery and not of a database round trip. The pre-filter is also only as safe as the tenant map is complete: a customer with no mapping is a silent gap, which is why an integrity check exists to catch it at seed time, before the gap can widen access. A structural guarantee still has a seam, and ours is in the seed data.

The same guarantee behind a chat window#

A boundary that only holds inside a library is a boundary nobody outside the engineering team has ever tested. So we put a chat front door on it and measured that too.

txttosql-eve is a Vercel Eve agent in TypeScript that lets a tenant’s ops user ask a question in Discord and get scoped charts and PDFs back [2]. The dependency points one way only: the agent wraps the Python core, the core never imports the agent, and no isolation logic is reimplemented in TypeScript. When the chat path needed a new capability, it was added in the core, in Python, with its own tests.

The token stays the boundary through the chat layer. A server-side map resolves a verified chat caller to a reference identity, an issuer mints a bearer token, and only that token crosses into the core. The tool the model calls takes a question and nothing else in its signature: no tenant id, no token. Nothing the chat user types and nothing the model generates can set scope. Anything beyond a read parks for human approval, consuming no compute until somebody decides, and even an approved write is then structurally rejected by the core’s read-only validator.

That approval gate surfaced a genuine bug worth telling honestly. An approval resumes on the approver’s turn rather than the asker’s, so reading the current identity at resume time bound scope to whoever clicked the button. The fix was to bind scope to the session initiator, which is the correct stance regardless: scope belongs to whoever asked, and the approver is a gate rather than an identity input.

Figure 7 - Diagram of the same question asked by two tenants in one chat workspace returning two disjoint sets of customer rows with zero overlap

Figure 7 - One question, two tenants, two answers: The identical sentence typed by two different callers returns two disjoint row sets, because the scope was resolved from the verified token rather than from anything in the message. This is the demo a non-engineer can watch work.

The measured result through the chat path is its own number, distinct from the core’s: 15 chat-driven queries, 0 cross-tenant rows, tenant A observing {c1, c2, c3} and tenant B observing {c5, c6} with no overlap, 1 write parked for approval, and 0 failing eval cases [2]. The identical suite runs against the live model and against a deterministic mock with no API key, and both produce the same table.

The deploy gate is the part most teams get wrong. A correct refusal often quotes the forbidden identifiers back in prose, so a naive scan of the model’s reply flags a passing case as a failure. The eval asserts on the rows the scoped tool actually returned instead, which survives a rephrased refusal and is a truer statement of the property being guarded.

Figure 8 - A model reply containing a forbidden identifier fails a naive reply scan, beside the scoped tool output containing only in-scope rows as the real assertion target

Figure 8 - Assert on ground truth, not on prose: The upper row is what the model said, which mentions the forbidden ids precisely because it is refusing correctly. The lower row is what the tool handed it. The boundary either held or did not in the lower row, so that is where the gate reads.

KEY INSIGHT: Gate your deploys on what the tool returned, not on what the model said about it. A security assertion that reads generated prose is measuring the phrasing of a refusal rather than the refusal itself.

Three caveats travel with this beat. Eve is beta, and its own README says the framework, APIs, and behavior “may change before general availability” [5], so versions are pinned and this is shipped through Phase 3 rather than done. The chat-user-to-token map is a real new trust surface that an operator has to provision and protect, covered by fail-closed probes but not made to disappear. The eval suite proves behavior rather than volume, since the core owns the volume number.

The floor: when the data should not reach a model at all#

Faraday answers a different question than the other two. The isolation core asks how to bound what a model sees. Faraday asks whether a document should cross a model boundary in the first place, and it has to answer that without uploading the document to find out.

It reads documents with an open-weight model, gpt-oss-safeguard-20b [6], on a local machine whose network is verifiably down, and reports what in them must never reach a cloud model. Every claim is scored against Microsoft Presidio [7], the free regex and NER baseline any client can run themselves, over a seeded synthetic corpus with known ground truth.

Faraday catches 26 to 28 of the 29 planted contextual exposures that Presidio catches none of, at contextual recall of 0.90 to 0.97 across sessions, runs, and quantized builds, stated as a range because temperature 0 does not give determinism across sessions, with 0.00 false positives per clean document in every recorded run against Presidio’s 1.90 [3]. On an adversarial set of 12 leaks authored to defeat both detectors, Faraday caught 10 in every run and Presidio caught 0.

The two documented failures are printed rather than buried. Denial framing defeats the scanner because a specific denial reveals its own subject and the model takes the negation at face value. Entity-free cross-paragraph assembly defeats it because the exposure exists only in a join that no chunk-level read makes. A clean report means no exposures this detector could find, not that the document is clean.

The offline claim rests on recorded evidence rather than an assurance: 19 outbound firewall block rules, three preflights recorded from inside the capture window, each proving the model was answering while every route was dead, and an unfiltered packet capture spanning a live scan containing 0 packets, with the verdict committed and re-verifiable from the artifacts alone. The interlock matters because loopback traffic never traverses the layer the capture reads, so an empty capture on its own proves nothing. The three passed preflights timestamped inside the window are what turn it into proof. The idea of demonstrating a local scan with the network down came from Nate B. Jones’s air-gap demo [8]. The measurement methodology and the evidence procedure are ours.

Figure 9 - Contextual recall of 0.90 to 0.97 against a baseline of 0.00, beside a false-positive panel showing 0.00 per clean document against 1.90, with an air-gap evidence timeline below

Figure 9 - The guarded delta, and what makes it honest: The left panel is the wedge where the regex and NER baseline is blind rather than weaker. The right panel is the guard that makes the left panel count, since a detection lead bought with false positives is not a lead. The strip below is the recorded window the whole claim rests on.

KEY INSIGHT: A vendor’s word is not a security boundary, and that includes ours. The offline claim is a recorded procedure an auditor can re-run from the committed artifacts, not an assurance that the network was down.

The same enforcement point, at every layer of the stack#

None of this is a house style. The same principle keeps turning up at different layers of production agent architectures, and we can point at five. One caveat travels with the set and should: all five are documented on AWS blogs, and three of them describe AWS’s own services, so this is convergence inside one large ecosystem rather than five unrelated teams. What transfers is that the enforcement point sits in the same relative position at every layer.

Figure 10 - Five-layer stack from SQL to retrieval to tool call to model access to tool contract, each annotated with the enforcement point that keeps disallowed data out of the model's context

Figure 10 - The same idea at five layers: Each row is a different place in an agent stack, and each carries the same rule: the disallowed thing is absent before the model is reachable, rather than filtered after the model has already seen it. The five were built for different workloads, though all five are documented on AWS blogs.

1. Row-level security at the SQL layer. PAR’s production architecture enforces boundaries deterministically at three points: cryptographic request signing with SigV4, semantic validation of the question before data is touched, and programmatic data isolation through split-plane SQL that pre-filters before the model is invoked [4]. They report “over 50,000 queries with zero cross-tenant data exposure incidents” [4]. Read that as what it is, PAR’s own self-reported claim rather than an audited result. In an article arguing that a vendor’s word is not a security boundary, treating a vendor’s word as proof would be self-defeating. What transfers is the architecture, not the number.

2. Live permission checks at the retrieval layer. AWS states that Bedrock Managed Knowledge Base runs real-time ACL checks on top of pre-retrieval filtering, that “the pre-filtered documents are transient for the life of the API call and are not visible to large language models (LLMs) or users,” and that this “maintains current access controls by checking permissions directly with the authoritative source at query time, rather than relying on potentially stale or incorrectly mapped ACL data” [9]. The durable idea is the distinction between a live check and a mirror. Most retrieval builds copy permissions at ingestion time and then drift silently as people leave teams and lose folder access, and the failure looks exactly like success until it does not.

Figure 11 - Diagram contrasting a live permission check against the authoritative source at query time with a nightly ACL mirror that has drifted out of date

Figure 11 - Live check versus stale mirror: On the left the permission is resolved against the system of record at the moment of the query. On the right it was resolved once, at ingestion, and has been quietly wrong ever since a folder membership changed. Both look identical from the chat window.

KEY INSIGHT: Ask any retrieval vendor one question: is that permission check live, or a nightly sync? The answer separates the teams who thought about this from the teams who have a diagram of it.

3. Deny-by-default at the tool-call layer. AWS describes an AgentCore reference architecture where access policy is authored in plain English, compiled to Cedar, and enforced at the gateway before the MCP server or the model is contacted, with a fail-secure property stated directly: “If the interceptor crashes, context is not injected. Cedar has nothing to permit, so the result is DENY” [10]. The genuinely novel part is the compiler, since authoring a rule in the language a compliance officer speaks and enforcing it in a language a machine evaluates closes a translation gap that usually leaks. AWS has since extended the same enforcement idea to what an agent may do over time, through temporal policies in AgentCore [11] and the Apache-2.0 Dogwood runtime-verification project [12]. Agent identity itself is not settled: the agent auth protocol is published as a v1.0 draft [13], and its authors are now at Vercel, which acquired Better Auth and says the team will bring agent identity to Vercel Connect [14], so for now the boundary has to be built rather than adopted.

4. Server-side enforcement at the model-access layer. The self-hosted gateway for Claude apps centralizes SSO, per-group model and tool policy, and spend caps, and AWS states the property that matters: “A developer whose group only grants Claude Haiku cannot bypass the restriction, even with a modified client” [15]. Upstream credentials never leave the control plane either, since, in AWS’s words, “No upstream credentials are distributed to developer machines” [15]. The same post carries the counterweight that keeps this from reading as an advertisement. Microsoft Entra ID does not include group or role claims by default, and without adding the group claim to the configuration the gateway “cannot resolve group membership and all users match only the catch-all policy” [15]. That is a control that fails open silently, which is worse than an absent control, since it produces the appearance of enforcement.

5. Enforcement inside the tool contract. For a regulated market-surveillance workload, AWS writes that “we separate the discovery of data from the retrieval to avoid hallucinations and strengthen the solution against injection attacks” [16]. The tool’s own docstring states the property: “The tool validates every filter against the report’s schema and builds a parameterised SQL query. The LLM never writes raw SQL, so filter values cannot be injected into the query” [16]. Enforcement is concrete rather than aspirational, with the allowed columns derived from the report schema, unknown filter keys raising before any SQL is built, and the row limit range-checked. This one cuts against a position we generally like, that a single schema-aware query tool beats a bespoke tool catalog. The tradeoff is real: flexibility on one side, a hard injection barrier on the other. Naming it as a tradeoff is more useful than pretending both are simultaneously true.

The cheapest leak is a clause, not an injection#

Everything above is isolation engineered inside an application. The cheapest leak we know of happens entirely outside it, costs nothing, and requires no attacker.

An engineer points a base-URL environment variable at a promotional inference endpoint to save money during a spike. No boundary is crossed in the code. Every test still passes. OpenCode’s own documentation is admirably direct about what that means on its free tier: each free model is “available on OpenCode for a limited time” while “the team is using this time to collect feedback and improve the model,” and the privacy section states that for those models, “during its free period, collected data may be used to improve the model” [17]. The terms are published, the arrangement is honest, and none of that helps if the traffic was a tenant’s data.

Nothing in a threat model catches this, because the threat model describes the application. This surface is contractual. The mitigation is a policy about which endpoints production credentials may point at, plus an approval path for changing one.

Where hardware takes over#

There is a version of this argument that runs deeper than software, and being clear about where it starts is part of an honest offer. Google’s prompt encryption SDK has a server prove it is running in a confidential environment by producing a TEE hardware quote, which the client SDK validates against policy and binds to the session before anything crosses the wire. The failure mode is stated plainly in Google’s own codelab: “If attestation fails, an AttestationError is raised and the prompt is never sent” [18]. That is the same principle argued throughout this article, enforced by silicon rather than by a library.

We do not sell that. We do not operate trusted execution environments, and we have no hardware-attestation product. For most multi-tenant analytics workloads a software-layer guarantee is the right level of investment, and structurally absent data is structurally absent whether or not the memory it never occupied was encrypted. A client whose regulatory posture genuinely requires hardware-attested isolation, health data crossing international borders or a financial-messaging vault, is a referral conversation rather than a build. Knowing where that line sits, and saying so before an engagement rather than during one, is worth more than pretending the line is not there.

Figure 12 - Isolation spectrum running from prompt rules through validators to structural scoping and hardware attestation, with a contractual surface drawn outside the technical stack entirely

Figure 12 - The spectrum, and the surface that sits outside it: Guarantee strength increases from left to right, and the software-layer band covers the large majority of multi-tenant analytics work. The hardware band is a referral, not an upsell. The contractual surface is drawn detached because no position on the spectrum protects against it.

Conclusion#

The claim in this article is narrow on purpose. A multi-tenant analytics agent cannot get its security guarantee from the model, from a prompt rule, or from a validator inspecting what the model produced. It can only get that guarantee from the disallowed data being absent from everything the model sees and everything its queries can reach. Our own strongest evidence is a test where the filter failed and nothing leaked: 605 scoped queries and 0 cross-tenant rows at the library boundary, 15 more and 0 through a live chat window, and a documented adversarial ceiling on both.

The convergence is the part worth carrying away. Five production architectures with different substrates and different threat models put the enforcement point in the same relative position: before the model, not after it. They are not five unrelated teams, since all five are documented on AWS blogs, so read this as a claim about where the enforcement point sits rather than as five independent verdicts. Splitting discovery from retrieval, compiling policy to a deny-by-default gate, checking permissions against the authoritative source at query time, and enforcing model access server-side are all the same move made at different layers. When five production architectures at five different layers keep making one move, that is usually the load-bearing one.

The two boundaries that stay outside the code are worth checking this quarter. Confirm which endpoints your production credentials are allowed to reach, since a promotional tier’s terms can undo perfect application isolation for free. Then confirm whether your regulatory posture actually requires hardware-attested isolation, because that is the one point on this spectrum a software library cannot reach, and knowing it before an engagement is cheaper than discovering it during one.

Ready to bolt-on the txtToSql engine to your data? The engagement is direct. We bolt the engine onto your warehouse behind a claim-verified tenant boundary, then give every tenant’s ops team a chat window onto their own data, and only their own data, with human approval on anything that writes and an eval suite that fails any deploy which could leak a row. If the question in front of you is the other one, whether that data should reach a cloud model in the first place, the Air-Gapped Document Exposure Scan is a fixed-fee assessment that stands the verified boundary up on your own machine, scans the document set you name, and hands back the findings, the evidence, and the runbook so your team can re-run it without us.


References#

[1] G. Dotzlaw, K. Dotzlaw, and R. Dotzlaw, “Structural Multi-Tenant Isolation for Text-to-SQL,” Dotzlaw Consulting, July 2026. https://dotzlaw.com/projects/txttosql-isolation-core/

[2] G. Dotzlaw, K. Dotzlaw, and R. Dotzlaw, “txtToSql-eve: A Chat Front Door With the Tenant Boundary Intact,” Dotzlaw Consulting, July 2026. https://dotzlaw.com/projects/txttosql-eve-chat/

[3] G. Dotzlaw, K. Dotzlaw, and R. Dotzlaw, “Faraday: The Verifiably Offline Document Exposure Scan,” Dotzlaw Consulting, July 2026. https://dotzlaw.com/projects/faraday/

[4] PAR Technology and Amazon Web Services, “Multi-tenant LLM analytics with row-level security: How we built a secure agent on AWS,” AWS Machine Learning Blog, June 2026. https://aws.amazon.com/blogs/machine-learning/multi-tenant-llm-analytics-with-row-level-security-how-we-built-a-secure-agent-on-aws/

[5] Vercel, “eve,” GitHub repository, 2026. https://github.com/vercel/eve

[6] OpenAI, “gpt-oss-safeguard-20b,” Hugging Face, 2026. https://huggingface.co/openai/gpt-oss-safeguard-20b

[7] Microsoft, “Presidio: Data Protection and De-identification SDK,” Microsoft Open Source. https://microsoft.github.io/presidio/

[8] N. B. Jones, “How To Run AI Locally On Files You Can Never Upload,” AI News & Strategy Daily, YouTube, Jul. 2026. https://www.youtube.com/watch?v=5slsNizN6MQ

[9] Amazon Web Services, “Build enterprise search for agents with Amazon Bedrock Managed Knowledge Base,” AWS Machine Learning Blog, 2026. https://aws.amazon.com/blogs/machine-learning/build-enterprise-search-for-agents-with-amazon-bedrock-managed-knowledge-base/

[10] Amazon Web Services, “Generate autonomous business insights with AI agent and MCP servers,” AWS Machine Learning Blog, July 2026. https://aws.amazon.com/blogs/machine-learning/generate-autonomous-business-insights-with-ai-agent-and-mcp-servers/

[11] Amazon Web Services, “Announcing temporal policies and rate limiting in Amazon Bedrock AgentCore,” AWS What’s New, August 2026. https://aws.amazon.com/about-aws/whats-new/2026/08/temporal-policies-agentcore/

[12] Amazon Web Services, “Introducing Dogwood: runtime verification for AI agents,” AWS Open Source Blog, August 2026. https://aws.amazon.com/blogs/opensource/introducing-dogwood-runtime-verification-for-ai-agents/

[13] Better Auth, “Agent Auth Protocol Specification v1.0-draft,” 2026. https://agent-auth-protocol.com/specification/v1.0-draft

[14] Vercel, “Vercel acquires Better Auth,” Vercel Blog, 2026. https://vercel.com/blog/vercel-acquires-better-auth

[15] Amazon Web Services, “Deploying Anthropic Claude apps gateway for AWS for enterprise workloads,” AWS Machine Learning Blog, August 2026. https://aws.amazon.com/blogs/machine-learning/deploying-anthropic-claude-apps-gateway-for-aws-for-enterprise-workloads/

[16] Amazon Web Services, “Market surveillance agent with LangGraph and Strands on AgentCore,” AWS Machine Learning Blog, July 2026. https://aws.amazon.com/blogs/machine-learning/market-surveillance-agent-with-langgraph-and-strands-on-agentcore/

[17] OpenCode, “Zen,” OpenCode Documentation, 2026. https://opencode.ai/docs/zen/

[18] Google, “Prompt Encryption SDK,” Google Codelabs, 2026. https://codelabs.developers.google.com/prompt-encryption-sdk

Multi-Tenant Agent Security: The LLM Is Not Your Security Boundary
https://dotzlaw.com/insights/ai-26-multi-tenant-agent-security/
Author
Gary Dotzlaw, Katrina Dotzlaw, Ryan Dotzlaw
Published at
2026-08-25
License
CC BY-NC-SA 4.0

Building production AI, or modernizing a legacy system?

That is the kind of work we do at Dotzlaw Consulting. Book a free 20-minute intro call and tell us what you are trying to build, or what is slowing you down.

← Back to Insights