Golemry
Back to blog

July 28, 2026

How We Build Secure Agents with Composio

Security is the floor, not the goal. The three walls we build at Golemry: credential isolation, tenant isolation, and a fixed tool scope. Oversight is the layer above.

How We Build Secure Agents with Composio

When our first users signed up, an agent job ran daily against our production database. It checked for new Golemry signups, looked up each user's onboarding state, and drafted a matching follow-up email. Unattended, against live customer data. Once the logic stabilized, we demoted the job to plain code, because it no longer needed AI judgment. But in the weeks it did, the agent version let us iterate on real feedback from day one, and we could only run it like that because of the architecture below.

If you're building an agent product, letting an agent do that should make you slightly nervous. An agent is non-deterministic and can be steered by its inputs, so the security question isn't whether it will always behave. It won't. The question is what a misbehaving run can actually reach. The principle to build on: structure over behavior. Anything that depends on the agent following instructions is a suggestion. What counts are walls, things a run cannot do no matter how confused or manipulated it is.

The three walls below apply to any agent stack. For each, we'll show how we build it at Golemry, where the tool layer, 900+ connectors, runs on Composio: it handles OAuth flows, token lifecycle, and webhooks per provider, keeps credentials in vaults, and executes tools sandboxed on its own infrastructure. Every auth flow you maintain by hand is another place credentials can leak, so buying that layer is itself a security decision.

The three walls side by side. Wall 1, credential isolation: the agent sits behind a divider from the vault that holds the account keys. Wall 2, tenant isolation: user 1, user 2, and user 3 each get their own vault, so one user's runs cannot reach another's. Wall 3, scope enforcement: a fixed grid of tools per job, some allowed and some blocked, settled before the run starts.

1. Keep account tokens off the agent machine

The account tokens themselves, Gmail, Slack, whatever your users connect, should never be transported to the agent machine. Whatever executes tools attaches them somewhere the agent isn't; the agent's world is requests and results. A prompt-injected agent can't exfiltrate what was never there.

You do have to transport something in the end, so make that something defensible. Keep it out of env vars, behind process isolation or a dedicated sidecar, away from any code the agent steers. And design the few credentials that do cross for damage control: easy to revoke, time-scoped where possible, always scoped to a single user, least privilege throughout.

In our setup, Composio holds the account tokens: we delegate the whole OAuth flow, they land in a vault, and tool calls execute sandboxed against it on Composio's side. What crosses to the agent machine is a single project API key, good for one user's project only, revocable in one step.

2. Give every user their own vault

If your product is multi-tenant, the second wall sits between your users. Tenant isolation should be a hard boundary at the integration layer, not row-level bookkeeping: one user's runs must not be able to see another user's connections, credentials, or events, even if your queries get it wrong. If your isolation lives in WHERE clauses, it's a rule. It should be a wall.

Our implementation: every Golemry signup gets its own Composio project, with its own vault, connections, and triggers, provisioned programmatically. It costs a project per user and a fleet of keys to manage. It buys the strongest isolation primitive available, placed exactly where multi-tenancy needs it. We've run this pattern in production for months.

3. Fix the toolset before the run starts

Scope tools per job, not per user. A job that needs read-Gmail and write-Sheets gets exactly those tools, and the set is fixed when the job's agent is instantiated, before it runs a single step. Nothing mid-run can widen it. From inside the run, tools outside the scope don't exist. A confused run can't wander into Slack, because there is no Slack.

This wall earns its keep twice. Against an attacker, it caps what an injected run can operate. And with no attacker at all, it protects you from your own agent, doing something it technically had access to but never should have touched. In Golemry, the scoping is enforced on our side, per job, at instantiation. It is the step most setups skip, handing the agent whatever is installed and calling it configured.

Outlook: from secure to safe

Security is the floor, not the goal. Walls bound what a run can reach, but they can't tell you whether the run was any good. A job that legitimately holds send-email can still send a bad email, and inside the mandate "bad" is a judgment, not a rule. Safe means more than secure: nothing bad happens, including by the agent's own hand.

That's the layer we build on top of these walls in Golemry. An independent overseer reads every run, including the ones where the input tried to steer the agent, and escalates what looks off, so a manipulated or derailed run doesn't ship silently. Where this heads is the overseer weighing in on actions before they go out. Walls for what can be made impossible, oversight for what can only be judged.

But build the walls first. They're the floor that let us point an unattended agent at our production database (with read access), and would let you do the same.

Fabian BothFabian Both

Founder, Golemry

Keep reading