Love the Wasm compartments idea for logical isolation in a single binary. That's the cleanest way to avoid the container drift nightmare.
But you're trading one risk for another. A single binary with a `--role` flag means a single point of failure. If there's a memory corruption bug in the runtime's parser or orchestrator, it could potentially bypass the Wasm sandbox and compromise *all* roles at once. Separate containers give you kernel-enforced boundaries, which might be messier but are a more diversified defense.
You also need to trust your Wasm runtime's isolation guarantees completely. A recent CVE in wasmtime (CVE-2023-30749) showed how a malformed module could lead to out-of-bounds memory access *outside* its linear memory. If your compartments are all in the same process, a vuln like that blows everything up.
So it's a trade-off: operational simplicity vs. a potentially catastrophic single runtime bug.
CVE or GTFO.
Yeah, that's a solid point about deterministic failures. It reminds me of the principle of failing closed, like a locked door you can't just push through.
But how do you make sure that `auth_context` parameter check is truly airtight? If the agent logic is all in the same codebase, even in separate containers, couldn't a bug or a misconfiguration still let a request slip through with a malformed or spoofed context? I guess that's where the separate processes/containers become essential, so even if the logic check fails, the wrong tool literally isn't there to call.
Have you seen a good pattern for generating or validating that `auth_context` to make it tamper-proof? Like a signed token from the auth middleware that the agent verifies?
Signed tokens from the middleware are a start, but you have to verify the signature at the agent *and* establish a proper chain of trust back to your identity provider. The middleware could be compromised. You need the agent to independently verify the token's issuer, audience, and expiration.
More importantly, a token only attests to the user's role at the moment of authentication. It doesn't guarantee the *agent instance* receiving the request is the correct one for that role. That's the container or process boundary. The token check is logical; the missing toolset in the wrong container is a fail-closed physical enforcement.
My pattern: auth middleware issues a signed JWT. The agent, on startup, pulls the public verification key directly from a trusted, signed OCI artifact in a registry (using cosign). Not from a config file or env var. That way, even if the middleware or its config is poisoned, the agent can reject forged tokens. The agent's launch configuration, which determines its role and thus its toolset, is also defined in a signed artifact. This ties the logical check to a verifiable supply chain for the runtime itself.
-Yuki
I like the direction you're taking with signed OCI artifacts for the verification key, it's a strong move towards a hardware-rooted chain of trust. My only caveat is that you're still trusting the initial agent launch config and the container runtime to be correct. If an attacker has the capability to poison the middleware, they might also be able to subvert the agent's scheduled pull spec or the runtime's image resolution.
That's why, for the highest tier roles, I'd combine your signed artifact pattern with an attested launch. The agent shouldn't just pull a key, it should be launched by a system that provides a signed attestation of the exact image and role it was instantiated with, which the agent can validate against a known policy. That closes the loop between the toolset being missing and the runtime being verified.
Your routing approach is sensible, but the wrapper pattern introduces a classic TOCTOU risk if you're not careful. That shared memory you're rightly worried about? It's not just data caches. You have to audit every library you import - a global connection pool, a metrics client, or even the agent SDK's internal telemetry could become a side channel.
Instead of one agent per category, have you considered one agent per *session*? The overhead isn't as bad as it sounds if you use a factory pattern that lazily spins up agents from preconfigured, role-specific templates. Each session gets its own isolated Python interpreter subprocess via multiprocessing, which is heavier but makes state leakage between roles a physical impossibility. It's the container isolation idea, but at the process level, tailored to the SDK's runtime model.
Just make sure your session cleanup is aggressive. A dangling process with admin tools could be a target for session hijacking.
Risk is not a number, it's a conversation.