Skip to content

2026

Can CrewAI Propagate a User's Identity Across Delegation?

If you need to propagate user identity across agent delegation, the honest answer for CrewAI is: not out of the box. CrewAI can absolutely hand work from one agent to another — that part works well and has for a long time. What it doesn't do is carry the requesting human along for the ride. When agent A delegates to agent B, the person who asked the question disappears, and B runs with whatever ambient credentials the process happens to hold. This post explains exactly where the principal is lost, what CrewAI actually does today, and how Promptise Foundry's CallerContext keeps user_id, tenant_id, roles, and scopes intact across every delegated hop.

Does the user's identity survive agent delegation?

The honest answer for most agent stacks is: not unless you thread it by hand. To propagate user identity across agent delegation — so that when an orchestrator acting on Alice's behalf hands a subtask to a peer via ask_peer or broadcast, the peer still runs as Alice — you normally have to pass the principal down every hop yourself. Miss it on one call and the peer runs unattributed: its memory search, its semantic cache, its conversation ownership, and its audit trail all detach from the real user. In a multi-tenant product, "unattributed" quietly becomes "cross-tenant," and that is the exact leak a security reviewer will find.

Pydantic AI vs Promptise Foundry: Typed Agents

If you're weighing Pydantic AI vs Promptise for a project that lives or dies on structured output, you've already found the crux of the decision: both frameworks give you typed, validated responses, but they draw the box around the problem very differently. Pydantic AI treats an agent as a typed function — clean, minimal, Pydantic all the way down. Promptise Foundry treats structured output as one layer beside memory, semantic cache, a sandbox, multi-tenant MCP, and runtime governance. By the end of this post you'll know which shape fits your stack, and you'll have runnable code for schema-strict output with automatic retry.

RAG vs Agent Memory: Which Does Your Agent Need?

If you have shopped around for RAG for agents, you have probably noticed that "memory" and "RAG" get used as if they were the same feature. They are not. Both push external text into the model's context, but they have different sources, different write paths, and — critically — different triggers. Confuse them and you end up bolting a document-retrieval pipeline onto a problem that a simple per-user fact store would have solved, or vice versa. By the end of this post you will have a clear decision table, a runnable Promptise Foundry example, and an honest read on when Promptise's built-in RAG is enough versus when you should reach for a dedicated ingestion library.

Cut Tool-Schema Tokens Without Per-Query Selection

The reliable way to reduce MCP tool schema tokens — the JSON definitions your agent ships to the model on every single call — is usually not the one teams reach for first. The headline move is semantic top-K selection: embed the query, embed each tool description, and send only the handful of tools that look relevant. It is the biggest single saver, and Promptise Foundry ships it. But it has two properties that rule it out for a lot of real deployments: it needs a per-query embedding pass, and it changes which tools the model sees from one request to the next. If your deployment is air-gapped, or your tool set has to be deterministic — every call presents the same tools, auditable and reproducible — per-query selection is off the table. This post is about the other half of optimize_tools: the graded static levels that shrink each tool's JSON schema deterministically, cutting tokens without ever changing tool availability.

Enforce Tenant Isolation with require_tenant=True

A require_tenant mcp server turns tenant isolation from a check you remember to add into an invariant the framework enforces at build time. Instead of adding a tenant guard to each tool by hand — and hoping the next tool, the next router, and the mounted third-party server all get one too — you set a single flag on the constructor, and every tool the server exposes is forced to authenticate and carry a tenant guard before you write a line of handler code. This post is about the exact mechanics of that flag: what MCPServer(require_tenant=True) does at build time, how to prove it with a runnable unit test, why it covers registration paths you didn't write yourself, and where it is honestly stronger than the opt-in checks other frameworks hand you.

How do you revoke an AI agent's access instantly?

To revoke an AI agent's access the moment it misbehaves, you need a single place to flip — not a scavenger hunt for a leaked string across every service that trusts it. That is exactly what a static per-agent API key can't give you: revoking it means minting a new one, editing every deployment that holds the old value, and redeploying without a gap — all while you may not even be sure which agent leaked it. Back the agent with an identity from your IdP instead, and revocation collapses into one directory operation: disable the identity, and its short-lived, audience-scoped credentials stop validating everywhere, with no server reconfiguration. This post shows the revoke path, why short-lived tokens keep the blast radius small, and how Promptise zero-fills any credential a running agent still holds in memory.

The Real Risks of Running AI-Generated Code In-Process

The risks of running AI-generated code are easy to underestimate, because the failure mode is invisible right up until the day it isn't: the program runs, prints a plausible answer, and only later do you notice it also read your .env, listed /, and made an outbound request you never authorized. This post is a threat-model walkthrough. We trace exactly what a model-written Python snippet can reach when it executes inside your process — the working directory and everything around it, environment-variable secrets, and the open network — using LangChain's PythonREPLTool as the worked example, and then show why Promptise Foundry treats a hardened container as the default path instead of something you remember to bolt on.

How to Roll Out a Breaking MCP Tool Change Safely

To roll out a breaking MCP tool change safely, you publish the new schema as a new version beside the old one and let each client migrate on its own clock — instead of editing the live tool in place and forcing every connected agent to move the instant you deploy. That second path is the default one, and it is why a one-line schema edit so often turns into an incident. An MCP tool's input_schema is a published contract: agents discovered it, built function calls to match, and will keep sending v1-shaped arguments until they change. Add a required field, rename a property, or tighten a type, and every in-flight caller starts getting rejected before your handler even runs.

Same user_id, Two Tenants: Why That Isn't Isolation

The problem with the same user_id across two tenants is that it looks fine right up until it doesn't: two of your customers, Acme and Globex, each have a user literally named alice, and the day both are active, whatever you key memory, cache, and conversation history on had better distinguish them. If that key is user_id alone, it doesn't — and the failure is silent. No exception, no log line, just Acme's alice occasionally reading Globex's alice's data. This post is about why a per-user key is not a per-tenant key, what an injective isolation key is, and the subtler risk most treatments skip: not just accidental collision, but deliberate forgery of another tenant's namespace.

Can Your Agent Exfiltrate Data? Sandboxing Code With No Network

To sandbox agent code with no network is the single highest-leverage control you can put between a code-writing agent and a data breach — because a program with an open socket doesn't need a bug to exfiltrate your data, it just needs a plausible-looking line the model was talked into writing. A code interpreter that "does some math" also has your process's network stack, and one urllib.request.urlopen turns a local read into a POST to attacker.example. Cutting the egress is obvious. The reason teams don't is subtler, and it's the honest problem this post is about: for most sandboxes, cutting the network also cuts the program off from the very tools it exists to use. This is how Promptise Foundry breaks that trade-off — NetworkMode.NONE, auto-set for the code-action pattern, where the isolated program's only reach to the outside world is your tools, invoked over a filesystem bridge that needs no network at all.

Stop Secrets Leaking into LLM Prompts and Tool Calls

Secret detection for LLM systems is the guardrail almost nobody instruments, and it is the one that quietly turns a helpful agent into an exfiltration channel. Everyone hardens the obvious surfaces — auth on the API, TLS on the wire, secrets in a vault — and then pipes raw user input, model output, and tool arguments straight past all of it. An API key pasted into a support chat, a DATABASE_URL echoed back in a debugging answer, an RSA private key baked into code the sandbox is about to run: each one is a credential leaving your trust boundary in plain text. By the end of this article you will know exactly where those leaks happen and how to layer a local, zero-network CredentialDetector over your agent so keys get caught the moment they appear.

Secure Agent-to-Agent Authentication in Practice

Secure agent-to-agent communication is the part of every multi-agent demo that quietly gets skipped: one agent delegates a task to another, the second agent acts, and when you open the log the only actor recorded is "the assistant." That is not an audit trail — it is a shrug. If a planner agent asks a payments agent to issue a refund, you need to know which agent asked, whether the callee was allowed to trust it, and where that decision landed in a tamper-evident record. By the end of this article you will know how Promptise Foundry propagates a verifiable caller identity through a delegation call and lands the answer to "who delegated to whom" in an HMAC-chained audit log.

Reflection, Self-Critique & Self-Consistency Agents

A self-critique agent is an LLM that checks its own work before it answers — it drafts a response, inspects that draft for mistakes, and fixes them in the same step. The appeal is obvious: catch the careless error before the user ever sees it. The catch is that reflection is not free, and most teams bolt it onto models that don't need it. By the end of this article you'll know which introspection techniques pay for themselves, which mostly burn tokens, and how to add a cheap self-check to a small model in a single line.

Can a Paraphrase Leak Another Tenant's Cached Answer?

A semantic cache cross-tenant leak is the failure mode that only similarity caching can produce: tenant B types a paraphrase of a question tenant A already asked, the two queries embed to nearly the same vector, and — without a caller-scoped partition — the lookup hands tenant B the completion Promptise stored for tenant A. An exact-match cache can never do this. It keys on the literal prompt string, so a reworded question misses and goes to the model. The moment you cache by meaning to save money, you also open a channel where meaning, not identity, decides who sees what. This post isolates that leak vector precisely, and shows how Promptise Foundry confines every similarity search to the caller's own tenant-qualified partition — by default, and fail-closed.

Should an AI Agent Approve Its Own Action?

Separation of duties for AI agents is the rule that the principal who requests a sensitive action can never be the one who approves it — and it is exactly the control that quietly collapses the moment whoever drives an agent can also click "approve" on the agent's own request. Most human-in-the-loop wiring stops one step short of this. It pauses before a risky tool call and asks a human to decide, which feels like dual control. But if the human answering the prompt is the same person (or the same service identity) that triggered the call, you have a rubber stamp with extra latency, not a second set of eyes. This post works through what dual control actually means, why the reviewer has to be a different principal, and how Promptise Foundry makes reviewer client_id != caller client_id a server-enforced default instead of a policy you hope everyone remembers to build.

Smolagents CodeAgent vs Promptise: Where Do Tool Calls Run?

The smolagents codeagent vs promptise code-action question is not "who lets the model write one program over your tools" — both frameworks do, and both do it well. It is a narrower, more consequential question: when that program calls issue_refund() or delete_customer(), where does that call execute, and what governs it? By the end you will know exactly what smolagents' CodeAgent does today, where Promptise's bridge draws a different line, and how a sandboxed program can still trip your approval gate and a hard call cap.

SPIFFE vs Entra vs AWS IAM: pick an agent identity provider

Choosing between SPIFFE vs Entra vs AWS IAM for AI agents is not really a question of which identity provider is best in the abstract — it is a question of which one your platform already issues workload identities from, because that is the one you can back an agent with today. If you have already decided your agents deserve their own verifiable identity instead of a shared key (see What Is Workload Identity for AI Agents?), the next decision is which provider to use. This post is a bake-off across the five Promptise supports — SPIFFE/SPIRE, Microsoft Entra, AWS IAM, Google Cloud, and generic OIDC — compared on the three things that actually differ between them: how the token is acquired, how you revoke it, and when each one fits.

How to Stop a Runaway AI Agent (Runtime Kill Switches)

To reliably stop a runaway AI agent you need a kill switch that acts on the process, not a counter that raises an exception inside one function call. That distinction is the whole game. Almost every framework hands you a per-run cap — max_iterations, recursion_limit, a usage limit — and calls it a safety control. But those caps raise an exception inside a single ainvoke(), and an exception only exists if there is a caller sitting there to catch it. The moment your agent is running unattended on a cron, a webhook, or a file trigger, there is no such caller: each trigger fires a fresh invocation, the counter resets to zero, and nothing halts the thing that is actually misbehaving. This post reframes the runaway agent kill switch as runtime enforcement — budget, behavioral-health, and mission breaches that become out-of-band pause/stop/escalate actions on a supervised AgentProcess — and shows you how to wire one in a few lines.

Where Does tenant_id Come From? JWT Claim vs API Key

Multi-tenant code usually takes a tenant_id for granted, but the real question is where that value comes from — and the two answers Promptise Foundry supports are a tenant_id from jwt claim and a tenant bound to each API key. Get that sourcing step right and the rest of your isolation story (tenant-qualified rate limits, per-tenant audit, cache scoping) follows for free. Get it wrong — a claim you forgot to read, a number where you expected a string, a request with no tenant at all — and a claim-less caller slips through as tenant-less, which is the one outcome a multi-customer platform can never afford.