22 of 37 Companies Enforce Agent Permissions, Still Share

You've set up an AI agent with a scoped API key, and it works. Then a second agent needs the same API, so you reuse the key. A third one borrows a teammate's login because it's faster. Six weeks later something deletes a batch of records, and your audit log says only "service-account-prod." Which agent did it? You can't tell.
That is the problem behind a recent VentureBeat survey: of 37 companies that enforce scoped AI agent permissions and have agents in production, 22 still run some or most agents on shared credentials. This post covers what that means, why it matters even for a five-person team, and how to fix it without buying an enterprise identity platform.
What the survey found (and what it doesn't prove)
The headline: enforcing permissions and having per-agent identities are two different things, and many companies have only done the first. According to VentureBeat, 54 of 137 respondents said their security program enforces scoped permissions at runtime. Of those, 37 also have agents in production. Of those 37, only 15 said every agent has its own scoped, managed identity. The other 22 have agents sharing credentials.
In this survey, "sharing" means one of two things:
- An agent runs on an API key that other agents also use.
- An agent runs on a credential borrowed from a human employee or a service account.
Widen the lens to all 68 respondents running agents in production: 42 said some or most of their agents share credentials, and only 26 said every agent has its own scoped, managed identity.
Earlier waves of the same tracker look similar. VentureBeat's June 2026 data (107 enterprises) had 69% with credential sharing somewhere in their agent fleet, and only 32% giving every agent its own scoped identity. The July wave (116 enterprises) had 63% sharing somewhere.
Some caveats before you quote these numbers anywhere:
- It's not about small businesses. The survey covers organizations with 100 or more employees. Don't read it as a statistic about solopreneurs or five-person shops.
- It's self-selected. Each wave is an independent, self-selected sample. VentureBeat fielded the August wave in 2026 and corrected the qualified sample from 141 to 137 after removing four respondents with internally inconsistent answers.
- Don't read a trend into it. June, July and August are different samples with different sizes. 69%, then 63%, then "22 of 37" tells you nothing about direction.
- Correlation is not causation. In the June data, companies with credential sharing anywhere had a security incident or near-miss rate of 63.5% (47 of 74), versus 40.9% (9 of 22) where every agent had its own scoped identity. Those are small groups, and VentureBeat itself notes the survey doesn't establish causation.
So what's the takeaway? Not "sharing causes breaches." It's narrower and more useful: even companies with permission enforcement in place often can't answer "which agent did this?" That's an accountability gap, and you can close it cheaply if you do it early.
Why shared credentials break accountability, not just security
Permissions answer "what is this credential allowed to do." Identity answers "who actually did it." Sharing doesn't stop you from enforcing the first, but it destroys the second.
Cobalt CISO Andrew Obadiaru put it this way, as reported by VentureBeat: with shared credentials you may be able to restrict what a credential can do, but it becomes much harder to tell which agent took an action, who authorized it, and whether one agent can be revoked without disrupting the others sharing that identity.
Three concrete failures follow from that:
- Forensics. The audit trail shows which account was used but not which agent acted. After an incident, you can't cleanly establish which agent did what.
- Revocation. With a shared service account, revoking one misbehaving agent means revoking access for every agent using that account. So you either leave the bad agent running or take down the whole fleet.
- Blast radius. If one agent is over-permissioned or compromised, it acts with the full reach of the shared credential, which is far more than that one job needed.
Here's what the difference looks like in a log. With a shared key:
{
"ts": "2026-10-03T14:22:07Z",
"principal": "svc-agents-prod",
"action": "crm.contacts.delete",
"count": 212
}
With per-agent identities:
{
"ts": "2026-10-03T14:22:07Z",
"principal": "agent:lead-dedupe-v3",
"on_behalf_of": "user:ops@yourco.com",
"action": "crm.contacts.delete",
"count": 212,
"run_id": "run_8f21c"
}
The second log tells you which agent, under whose authority, and in which run. That's the difference between a ten-minute investigation and a day of guessing.
The small-team version: what "its own identity" means in practice
An agent identity is a separate credential, with its own scope, its own name in the logs, and its own off switch. You don't need a directory service to get that. You need a naming convention and one credential per agent per system.
The minimum bar, per agent:
- Its own credential for each system it touches. No reusing another agent's key, and no borrowing a human's login.
- A scope limited to its job. A lead-enrichment agent gets read on the CRM and write on two fields, not admin.
- A name you can grep for. Something like
agent-inbox-triage-prod, so it shows up legibly in the provider's logs. - An owner. One named human who answers for it.
- A kill switch. You can revoke this one credential without touching any other agent.
For a small team, a simple inventory is more than most companies have. Keep it in a repo:
# agents.yaml - one entry per agent, reviewed monthly
agents:
- id: agent-inbox-triage-prod
owner: lazar@yourco.com
purpose: label and route inbound support email
systems:
- name: gmail
scope: gmail.modify # label/archive only, no send
credential: gmail-triage-oauth-client
- name: helpdesk
scope: tickets:create
credential: helpdesk-triage-key
can_send_external: false
revoke: "rotate helpdesk-triage-key; disable gmail-triage-oauth-client"
- id: agent-invoice-draft-prod
owner: lazar@yourco.com
purpose: draft invoices from closed deals
systems:
- name: accounting
scope: invoices:draft # draft only, no send, no void
credential: accounting-draft-key
can_send_external: false
revoke: "delete accounting-draft-key"
That file is your answer to three questions an auditor, a client, or you at 2 a.m. will ask: what agents exist, what can each one touch, and how do I shut one off.
Step by step: moving from shared keys to per-agent identities
Do it in this order: inventory, split, scope, label, then test revocation. You can finish the first pass in an afternoon for a small fleet.
1. Inventory what exists
List every agent, automation, and script that calls an API or logs in somewhere. Include the ones that "just use my login." Those borrowed human credentials are the riskiest, because the agent acts as you with all your permissions.
# Rough starting point: find where credentials are referenced in your repos
grep -RIn --include="*.py" --include="*.env*" --include="*.yaml" \
-E "(API_KEY|SECRET|TOKEN|PASSWORD)" . | sort | head -50
This won't find everything (n8n credentials, Zapier connections and no-code tools hide theirs in dashboards), so check those by hand.
2. Split shared credentials
For each key used by more than one agent, create one new key per agent and move each agent over. Most SaaS tools let you create multiple API keys or OAuth clients. If a tool only offers one key per account, that's worth knowing: either create a dedicated service user per agent, or put a thin proxy of your own in front of that tool so you can log per-agent (more on that below).
3. Scope each one down
Start from "nothing" and add permissions until the agent's job works, not the other way around. Two rules cover most cases:
- Drafting is not sending. Let the agent create drafts, tickets, or proposed changes, and keep the irreversible action behind a human or a separate, more tightly controlled step.
- Read-only by default. Add write scopes per field or per object type only when a task needs them.
4. Make the identity visible in logs
Many APIs record the key's name or ID, so name your keys well. For anything you call through your own code, tag every request and log line with the agent ID and run ID:
import logging, uuid, requests
AGENT_ID = "agent-lead-dedupe-v3"
def call_crm(path, payload, api_key):
run_id = f"run_{uuid.uuid4().hex[:6]}"
headers = {
"Authorization": f"Bearer {api_key}",
"X-Agent-Id": AGENT_ID, # only useful if the API echoes or logs it
"X-Run-Id": run_id,
}
resp = requests.post(f"api.example-crm.com{path}",
json=payload, headers=headers, timeout=30)
logging.info("agent=%s run=%s path=%s status=%s",
AGENT_ID, run_id, path, resp.status_code)
return resp
Don't rely on custom headers alone. Many providers ignore them, so your own log is the record you control, and the per-agent key is what makes the provider's log useful too.
5. Test revocation before you need it
Pick one agent and kill its credential on purpose. Confirm that agent fails and every other agent keeps running. If revoking one thing breaks others, you still have a shared dependency somewhere. This ten-minute test is the most honest check of whether you actually fixed the problem.
Where the identity tooling stands (and what's free)
Dedicated agent-identity products exist and are consolidating, but adoption is thin and you don't need one to start. The VentureBeat survey asked 108 respondents which platforms they use to secure agents. Only 2 named Microsoft Entra Agent ID, 1 named Okta, and 2 named a non-human identity platform. For comparison, 53 named OpenAI, and 48 each named Microsoft Azure and Google Cloud. In other words, most teams are leaning on their model or cloud vendor, not a dedicated identity layer.
The vendor landscape is moving, though. Per VentureBeat, Cyera completed its $1 billion acquisition of Oasis Security on September 3, and Cisco closed its acquisition of Astrix Security on June 29.
One development is worth a close look if you already use Okta. On August 24, 2026, Okta announced general availability of Agent SSO. It registers AI agents in Universal Directory and issues short-lived, identity-governed tokens in place of stored credentials, and it's included in core Okta SSO plans at no additional cost. Two limits apply:
- It only works for AI agents that support the Cross App Access standard.
- Okta for AI Agents, which covers broader discovery and governance, is a separate paid subscription.
Check Okta's current documentation and your own plan before assuming it covers your agents.
A rough way to decide what to use:
| Situation | Reasonable starting point |
|---|---|
| 1-5 agents, no identity provider | Per-agent API keys + agents.yaml + your own logging |
| Already on Okta or Entra, agents support the needed standards | Evaluate the vendor's agent identity features first |
| Many agents, multiple teams, compliance requirements | Dedicated non-human identity tooling, plus the manual discipline above |
| Agents on tools that only allow one key per account | Dedicated service user per agent, or a logging proxy |
The tooling shortens the work, but the discipline (one agent, one identity, one scope, one owner) is the part that matters and costs nothing.
Isolation and incidents: why identity is only half the fix
Per-agent identity tells you who acted; isolation limits how much damage one agent can do. The survey suggests most companies are weak on the second part too.
Per VentureBeat, only 12 of 137 respondents said high-risk agents run in isolation with a bounded blast radius. (VentureBeat's pieces report this figure differently, so don't treat any isolation percentage as settled.) Meanwhile, 64 of the 109 organizations running agents in production or a pilot reported an agent-caused security incident or near-miss in the past 12 months. Again, the survey doesn't establish that one causes the other.
For a small team, "bounded blast radius" can be plain and cheap:
- Spending and rate limits. Cap API calls and, where the tool allows, dollar amounts per agent per day.
- Approval gates on irreversible actions. Sending external email, issuing refunds, deleting records, and changing billing all get a human step or a second check.
- Separate environments. Agents that experiment run against a sandbox or a copy, not production data.
- Alerting on unusual volume. If the dedupe agent normally touches 20 records a day and suddenly touches 2,000, someone should hear about it.
# Simple per-agent guardrail: refuse bulk destructive actions without approval
MAX_DELETES_PER_RUN = 25
def guarded_delete(agent_id, record_ids, approved=False):
if len(record_ids) > MAX_DELETES_PER_RUN and not approved:
raise PermissionError(
f"{agent_id} tried to delete {len(record_ids)} records; "
f"limit is {MAX_DELETES_PER_RUN} without approval"
)
return crm_delete(record_ids)
Notice what makes this guardrail work: it knows which agent is asking. A shared identity can only enforce one limit for everyone. Per-agent identities let you give the low-risk summarizer a wide limit and the record-deleting agent a tight one.
A monthly review that takes 20 minutes
Identity hygiene decays unless someone checks it on a schedule. Agents get added in a hurry, keys get reused "just for now," and the inventory drifts out of date. Put a recurring check on the calendar:
- Open
agents.yaml. Does every running agent appear in it? Does every entry still run? - For each system, list the active API keys or OAuth clients. Does each map to exactly one agent? Delete orphans.
- Search for any agent running on a human's personal login. Replace it with its own credential.
- Pick one agent and rehearse revocation. Confirm the others stay up.
- Skim the last 30 days of logs for agents acting outside their stated purpose or hitting scope-denied errors. Those errors often mean an agent is trying things you didn't plan for.
If you do only this, you'll be ahead of the 22 companies in the survey that enforce permissions but can't say which agent did what.
My own approach
I'm a senior engineer who builds AI automations for solopreneurs and small teams, and the rule I recommend starting from is simple: one agent, one credential, one narrowly scoped job, and a log line that names the agent. In practice I'd suggest splitting shared keys into per-agent credentials, scoping each one down to the minimum the task needs, putting irreversible actions behind approval steps, and setting up logging so a question like "which agent changed this record?" has a direct answer. I'd also run the revocation test, so you know you can switch one agent off without taking the rest down.
Work with BizFlowAI
If you'd rather have this built for you, that's what we do: production AI automation for solo founders and small teams — agents, integrations, and document pipelines that actually ship.
Book a free discovery call — 30 minutes, we map the highest-ROI automation in your workflow. No pitch deck, just engineering.
More guides like this on the BizFlowAI blog.
Frequently asked questions
Why is sharing API keys between AI agents a problem?
When several agents use the same API key or service account, your audit log shows only the shared account name, not which agent acted. That makes incident investigation slow and often inconclusive. You also can't revoke one misbehaving agent without cutting off every other agent using that credential. A compromised or over-permissioned agent also acts with the full reach of the shared key.
What does it mean for an AI agent to have its own identity?
An agent identity is a separate credential per agent per system, with its own scope, a recognizable name in the logs, a named human owner, and its own off switch. For example, an agent named agent-inbox-triage-prod gets only the permissions its job needs. You don't need an enterprise directory service to do this, just a naming convention and one key per agent.
How do I find out which AI agent performed an action in my systems?
You need each agent to authenticate with its own credential so the provider's logs record a distinct principal such as agent:lead-dedupe-v3. Ideally the log also records who the agent acted on behalf of and a run ID. If a tool only supports one key per account, create a dedicated service user per agent or put a thin logging proxy in front of that tool. Without per-agent credentials, the log can only tell you which shared account was used.
How do I move AI agents from shared API keys to per-agent credentials?
First, inventory every agent, automation and script that calls an API, including ones using a human's login. Then create one new key or OAuth client per agent and migrate each agent to its own. Scope each credential from zero upward, so drafting is allowed but sending or deleting is not unless required. Finally, label each identity clearly and test that you can revoke a single agent's credential without breaking the others.
Do small teams need to worry about AI agent credential sharing?
Yes, because the accountability problem appears as soon as two agents share one key, regardless of company size. The VentureBeat survey behind these numbers covered organizations with 100 or more employees, so it doesn't measure small teams directly. Still, a small team can fix it cheaply with one credential per agent and a simple agents.yaml inventory listing owner, scopes, and how to revoke each agent. Doing it early is far easier than untangling shared keys after an incident.