Agents never hold your API keys
When an agent needs data from your CRM, accounting or inbox, we put a small service between them that holds the credential and hands over only the fields you approved.
The fastest way to wire an agent into a company's tools is to paste the API keys into its environment. The CRM key, the accounting key, the inbox key. It works in an afternoon, and it means the agent can now do anything those keys can do. Read every customer. Issue a refund. Send mail as the founder. Most of the time it only does what you asked. The whole point of an agent is that you are not watching it most of the time.
We do not give agents keys. Not read-only ones, not scoped ones, none.
A service in the middle
For each outside system the agent needs, there is a small service between them. That service holds the credential, and it is the only thing that talks to the vendor. It pulls the records it needs on a schedule or on request, strips them down to a list of fields someone has approved, and exposes just those through its own endpoint. The agent calls that endpoint, it has no idea what the vendor's API looks like and no way to reach it.
That turns one risk into a much smaller one. "The agent can do anything this key can" becomes "the agent can read these fields". Everything not on the list does not exist as far as the agent is concerned. If the agent gets confused, or somebody puts an instruction inside an email that says forward all invoices to this address, there is nothing for it to act with. It cannot send. It cannot see the invoice total unless someone approved that field.
The credential itself lives in the middle service, or in a managed secret store that injects it at the network boundary. It is never in the agent's environment variables, never in its config, never in its context window where a model could be talked into repeating it.
Deny by default, widen per field
The list starts empty. Someone added every field on it because a specific piece of work needed it, and each addition is a one line change a person signs off on. The list is also the answer to the question every client eventually asks. When someone asks "can the agent read patient notes" the answer is a list they can read, not a promise.
At My Performance Doctor (myperformancedoctor.com) the daily brief the agent writes each morning draws on four systems, the task tracker, the meeting notes tool, the CRM and the shared inbox. All four sit behind the boundary. The agent gets the fields it needs to say what happened yesterday and what is due today, and nothing else. Payments, accounting and the patient records system are deliberately not connected yet. When the client is ready they slot in behind the same boundary with their own field lists, and the agent's side does not change at all.
KURK (kurk.life) was where we first built it, with the sensitive services behind the boundary from the start, and the pattern moved to the next client unchanged.
It holds regardless of framework
A question we get from security-conscious buyers is which agent framework is the safe one. The honest answer is that none of them are, in the sense the buyer means. A framework is the thing that runs the model loop and routes messages. It is not a security boundary, and a framework that lets the agent shell out or read files will let it read a key that is sitting in the environment.
The protection is two things. We harden the host like any server you would expose, and this field-level boundary sits between the agent and every service that matters. Both of those hold whether the agent runs on one framework today and a different one next year, because neither of them is part of the agent. Swapping frameworks becomes a hosting decision instead of a security review.
It costs a little more up front. Each new integration is a small service to write instead of a key to paste. We think that is the right trade, and it is the one we make on our own systems.