How to Build Secure Agentic Systems
Learn the architecture we recommend for agents that never hold your keys: a deterministic orchestrator, a sandboxed agent with a short-lived session, and a transparent proxy that adds the real credentials on the way out.
Looking to improve your secret management processes?Talk to an expert
How to Build Secure Agentic Systems
Most teams run agents the same way at first. There is an on-call agent, a growth agent, and a support agent, each on its own VM that stays up, and each box holds the API keys that agent needs as environment variables. It works, and it is where almost everyone starts.
The trouble is what happens next. This walkthrough lays out a different shape for agentic systems: deterministic code around a non-deterministic agent, where the agent holds a session instead of keys and a proxy adds the real credentials on the way out. It is the pattern we recommend, and it is the pattern Agent Vault is built around.
Secret sprawl, agent edition
Every new agent means another box and another copy of the keys. A Stripe key ends up on two boxes, a laptop, CI, and a `.env` file. A Slack token ends up on three. This is secret sprawl again, now for agents, and nobody has one place to see which agent holds which key or to take access away.
Agents make this worse than it was for ordinary applications, because agents act on what they read. One poisoned GitHub issue can instruct an agent to dump its environment and send it somewhere, and every key on that box is gone. That is prompt injection, and it does not even need to be deliberate. An agent debugging its own output can print a credential to the terminal, and that text goes to the model provider as part of the conversation.
So organizations end up needing a central place that controls what each agent can reach, without handing the agent the keys. The credential brokering explainer covers the exfiltration problem in more depth.
Split the system in two
The recommendation is to split the system along one line: the parts that are deterministic, and the agent, which is not.
On the deterministic side sits normal code you can reason about. There is an interface where tasks come in, such as Slack. There is an orchestrator. There is Infisical, holding the keys. And there is a proxy that adds the real key to the agent's requests as they leave.
The agent sits alone on the other side, in a sandbox. Instead of keys, it holds a temporary pass that only works at that proxy.
Everything on the deterministic side is the environment around the agent. That environment is what decides whether the agent can do good work safely, and it is what organizations need to design. The model's behavior is not the control point. The code around it is.
The vocabulary: services, bundles, proxy, identity, sessions
Infisical is a secrets manager: one central place for your keys instead of copies on every box. Agent Vault is the part of Infisical built for agents. The keys stay in Infisical, and the agent never gets them. Five concepts cover the whole setup.
A service is an API or MCP server plus the real key for it, like `api.github.com` with a GitHub token. The key goes in once and is never shown again.
An access bundle is a list of services one kind of agent is allowed to use. An on-call agent gets GitHub and Sentry. A growth agent gets Stripe.
The proxy is a small program you run on your own infrastructure. Every request the agent makes goes through it, and it adds the real key on the way out. It only lets through hosts in the bundle and refuses everything else. The proxy logs in to Infisical with a proxy token, and one token can start as many proxies as you need.
A machine identity is a login for code instead of a person. Your orchestrator uses one to talk to Infisical.
A session is a temporary pass for one access bundle. The agent holds the session token instead of keys. It only works at your proxy, and it stops working when it expires or you revoke it. Every request made with a session, allowed or denied, shows up in that session's logs.
The rest of the video is about how those pieces fit together.
The orchestrator is deterministic
The orchestrator is not an agent. It is plain code, and it makes the same decision every time. Given the same input, it produces the same output, which is exactly what the model cannot promise.
The orchestrator decides which agent runs, what access it gets, where it runs, and when it stops. The model never gets a say in any of that. If a message arrives in the on-call channel, the orchestrator picks the on-call bundle, mints a session, starts a sandbox, and revokes the session when the job is done.
An orchestrator is anything that creates a session and starts an agent with it. That can be a backend service, a CI job, a queue worker, or a cron job. It can also be you, creating a session in the dashboard and pasting the token into an agent at home. Agent Vault does not care which. It only sees the session.
How tasks reach the orchestrator
Something has to turn real-world events into tasks. That is the interface.
For a lot of teams it is a Slack app: someone mentions the bot, and the app hands the message to the orchestrator. It could also be a webhook from GitHub or Sentry, a form, an API call, or a schedule. The interface carries the reply back too, so the answer shows up where the person asked.
One detail matters later. The interface knows who asked.
What a session actually does
The orchestrator logs in to Infisical as a machine identity and mints a session for one task. The session says which services the agent can use and how long it lasts, an hour for example. Infisical hands back a session token. The orchestrator starts the sandbox and gives the agent that token, and nothing else.
Every request the agent makes carries the token to the proxy. The proxy checks it with Infisical, confirms it is valid and which key applies, then adds the real key for that service and sends the request on to the upstream API. If the agent tries to reach a host that is not in the bundle, the proxy refuses it before it leaves your network.
The token only works at your proxy and only for those services. Stolen, it is useless anywhere else. When the task is done, the orchestrator revokes the session. If it never gets the chance, the session expires on its own. Either way there is nothing to rotate. The how it works doc covers the request flow step by step.
Many ways to slice it
There is no one right way to build this. Every team ends up making a handful of choices, and the orchestrator is where they get made.
- Harness. Claude Code, Codex, or your own agent loop. You can run more than one.
- Where it runs. A fresh sandbox for each task, or a box that stays up.
- Access. Which services this run gets. That can be a bundle, specific services, or whatever the person who asked is allowed to do.
- Lifetime. How long the session lasts. One task, a day, or until you revoke it.
Mix them however you want. The bottom layer stays the same: the agent gets a session instead of keys, and its traffic goes through the proxy. The setup planning doc walks through these choices.
Long-running agents still fit
Not every agent finishes. A chat bot, or an OpenClaw instance at home, keeps running.
The pattern is the same with a longer session. An ephemeral agent gets a session per job with a lifetime a bit longer than the job, revoked when done. A long-running agent gets one session that never expires, or one that lasts 24 hours before the orchestrator swaps in a fresh token. Revoking the session is how you cut it off.
Ephemeral is still the better default when the agent allows it. A session that dies with the job cannot be reused later.
On behalf of: the agent acts as the person who asked
At the end of the day, agents do things on behalf of people. The same agent should act as Jake when Jake pings it and as Tony when Tony does.
That is agent identity. The agent has its own identity, and it is acting for a user who has theirs. What it should be able to do is the intersection of the two: only what both the agent and that user are allowed to do. The interface knows who asked, so the orchestrator can pass that along when it mints the session.
In Agent Vault, a service can take each person's own credential, which Infisical calls a personal value, and a session created on behalf of a user uses that person's values. The orchestrator's machine identity gets permission to mint sessions for specific people, and both the identity and the person have to hold the bundle. The agent never gets more access than the person who asked for it.
Transparent proxy versus gateway
MCP gateways and AI gateways work by having everything authenticate to the gateway. The gateway then calls tools on the agent's behalf, and the agent has to be configured to talk to it. That covers one protocol and requires an intrusive setup.
A transparent proxy sits in the path instead. The agent makes normal calls with a placeholder key, and the proxy adds the real one on the way out. The agent does not know it is there. It can connect to an MCP server, hit an HTTP endpoint, use an SDK, or shell out to a CLI. It does not matter, because the proxy hooks into the `HTTPS_PROXY` environment variable that almost every HTTP client already respects. Infisical holds and refreshes OAuth tokens for upstream MCP servers too.
The practical payoff is that you can swap the model or the harness without touching how access works. The MCP gateway video goes deeper on why a gateway alone does not stop credential exfiltration.
Where it runs
The sandbox can be a Docker container, a Kubernetes pod, a plain VM with no Docker, or a managed sandbox like Modal or Daytona. The pattern does not change. Only where the agent runs does.
Apollo, end to end
Apollo is an agent we run internally with access to the Infisical GitHub repository. Slack is the interface. Someone mentions it, and the message goes to a deterministic orchestrator.
The orchestrator mints a session and creates a Modal sandbox for the task. Each sandbox has a sidecar, a second container right next to the agent that runs the Agent Vault proxy. The agent's container cannot reach the internet directly, so all of its traffic is forced through the sidecar. That is where credentials get brokered.
Every sidecar starts from the same proxy token, so this works the same with one sandbox or ten thousand. When the task is done, the reply goes back to the Slack thread, the session is revoked, and the sandbox is gone. It is fast, and the agent never holds a key.
It is all programmatic
There is a UI in Infisical for access bundles and sessions, and it is useful for seeing what Apollo can reach, which sessions are live or revoked, and every call each one made. But none of what Apollo does needs it.
The orchestrator authenticates to Infisical as a machine identity, mints the session, and revokes it, all through the API. The same flow is available from the CLI. The proxy starts from a proxy token. No one clicks anything per task. This is not an infrastructure project. It is a few API calls in the deterministic part of your system.
The pattern in one breath
Split your system into deterministic code around a non-deterministic agent. The orchestrator decides. The agent gets a session, not keys. The proxy adds the keys on the way out.
Slice it however you want: ephemeral sandboxes or long-running boxes, any harness, any platform. The pattern is the same. For a tour of the product itself, see how Agent Vault works.
Starting with Infisical is simple, fast, and free.