AI agents increasingly need to reach private resources: an internal inventory API, a ticketing system, a reporting database, an internal wiki. An agent is not a person. It works without a sign-in prompt, it acts at machine speed, and it can be steered by the content it reads. A shared human account, a long-lived API key in a configuration file, or broad network access makes each of those traits more dangerous.
Cloud Secure Edge (CSE) treats an agent as a non-human identity. Each agent gets a Service Account that CSE Roles and Web Policies can authorize, scope to specific apps and paths, audit, and revoke, independently of any person's account. Agents that run on a platform with its own identity, such as GitHub Actions, Google Cloud, or Kubernetes, authenticate with short-lived tokens the platform issues, so no secret is stored with the agent at all.
This guide covers agents that act on their own. If the agent runs on an employee's device and acts for that person, such as a desktop assistant or a coding agent, it has no identity of its own and nothing here applies to it. See Secure agents that run on a user's device instead.
An agent with its own identity reaches a private app through a Hosted Website. Every request follows the same path.
The calling platform does not need to be added to the Unregistered Devices allowlist. Hosted Websites are served with publicly trusted TLS certificates, so the platform does not need to import a certificate either.
Setting this up means answering two independent questions. They compose, so answer both before you start. An agent on Kubernetes that queries a database answers the first question with a narrow interface and the second with a workload identity.
CSE publishes HTTP. What the agent needs decides whether you can publish it directly.
| What the agent needs | What you publish |
|---|---|
| A web app or an HTTP API | The app itself, as a Hosted Website |
| A database, a server, or another non-HTTP resource | A narrow HTTP interface in front of the resource, as a Hosted Website. See Publish a narrow interface |
Where the agent runs decides what credential it can present.
| Where the agent runs | Credential | Service Account type |
|---|---|---|
| On a platform that issues OIDC tokens, such as GitHub Actions, Google Cloud, or Kubernetes | A short-lived JWT the platform signs | External JSON Web Token (JWT). See Authenticate with a workload identity |
| On a platform that can send an HTTP header but cannot issue OIDC tokens | A static key | SonicWall CSE Generated Key or External API Key. See Authenticate with an API key |
Prefer a JWT wherever the platform supports it. CSE validates the token against your issuer on every request and the token expires on its own, so there is no secret to store, share, or rotate.
Skip this section if the agent calls a web app or an HTTP API. Publish that app as a Hosted Website and go to Set up access for an agent.
When the task involves a database, a server, or another non-HTTP resource, do not give the agent network access to the resource. Put a narrow interface in front of it and publish the interface:
get_stock_level or list_open_tickets.The interface runs inside your network next to the resource, and it holds its own least-privilege credentials to that resource, such as a read-only database user. The agent never sees those credentials and never has a network path to the database.
| Agent task | Publish this instead of network access |
|---|---|
| Answer questions from a sales database | An MCP server with read-only query tools, backed by a read-only database user |
| Open or update tickets | The ticketing system's API, limited by Layer-7 rules to the ticket paths the agent needs |
| Restart a stuck service | An internal API with one endpoint per approved runbook action |
Two design points matter here, because they are hard to change later.
Layer-7 rules match URL paths, not tool names. CSE cannot see the individual MCP tools named inside a request body. To give different agents different powers, publish read-only and write tools as separate MCP endpoints, which means separate paths, or as separate Hosted Websites with their own Web Policies.
Watch for an Authorization header collision. If the MCP server or API authenticates with the Authorization header itself, for example with OAuth, send the CSE credential in a custom header instead. That choice is made in Step 3.
Publish the interface as a Hosted Website through your Connector or Access Tier, then continue below.
These four steps are the same whichever credential the agent presents.
Go to Directory > Service Accounts and select + Add Service Account, then choose the type you settled on in Choose an authentication method and configure it:
2.1 Create a Role for the agent. Under Role Attributes, add the By Service Account attribute, select + Attach Service Account, and choose the Service Account from Step 1.
Give each agent its own Service Account and its own Role. Two agents sharing one identity cannot be told apart in your access records, and cannot be revoked separately.
2.2 Add the Role to a Web Policy, under Private Access > Access Policies.
2.3 Optionally, limit the agent to exactly what it needs with API-level (Layer-7) rules. For example, allow READ on /api/v1/stock* and nothing else. Actions are READ, WRITE, CREATE, UPDATE, or ALL. Resources are URL paths with optional wildcards, and a ! prefix denies a path.
Trust Scoring is not evaluated for Service Accounts. There is no device to evaluate, so a minimum Trust Level in the policy does nothing here. The credential, the Role, and the Layer-7 rules are the whole control. Keep all three tight.
3.1 Go to Private Access > Hosted Websites and open the website. If the app is not published yet, see Register a Hosted Website to Users.
3.2 On the Access Permissions step, turn on Enable Service Account Access.
3.3 Under How should the Service Account credentials be sent?, choose where the credential travels. The agent has to send it in exactly that location:
| Token location | Choose it when |
|---|---|
| Authorization header | The default choice for most agents |
| Custom header | The app authenticates with the Authorization header itself, for example with OAuth |
| Query parameter | Nothing else is possible. A credential in a query parameter is written into every log that records the URL |
3.4 Confirm that the Web Policy from Step 2 is attached, and save the website.
Send one request by hand before you let the agent run:
curl -i https://inventory.example.com/api/v1/stock -H "Authorization: Bearer $TOKEN"
A successful request returns the app's response. A missing or invalid credential, or one sent in a different location than you configured, is denied before it reaches the app.
Then check the console. Go to Home > Events to see allowed and denied Service Account requests, or open the Service Account under Directory > Service Accounts and review its Access Activity tab. Denied requests are often the first sign of a misconfigured or misbehaving agent.
Come back to the Access Activity tab periodically once the agent is running. It shows what the agent actually reached. An agent reaching something you did not expect is a scope problem to fix in the policy, not in the agent's instructions.
The platform running the agent proves who the agent is, and CSE decides what it can reach. There is no key to store, share, or rotate.
In Step 1, select External JSON Web Token (JWT). The Type field shows Generic OIDC, because CSE accepts any OIDC-compliant issuer.
1. Enter the Issuer URL, for example https://token.actions.githubusercontent.com.
2. Enter an Audience, which is a URI or URL, and the Subject allowed to use it.
3. Select Add Audience Group to allow more combinations, such as the same workflow calling a second Hosted Website with its own audience.
Use a distinct audience for each Hosted Website, such as the website's own URL. A token minted for one app then cannot be replayed against another.
Subjects accept regular expressions, which helps when one agent runs from several branches or environments. Anchor the expression to the full value and keep it as narrow as possible, because anything it matches is admitted:
^repo:example-org/inventory-agent:ref:refs/heads/(main|release)$
Then finish Steps 2 through 4 of Set up access for an agent.
The agent requests a token for the audience you configured, then sends it as a Bearer token. Open the platform you use.
Use a key when the platform cannot issue an OIDC token you control but can send an HTTP header with every call.
In Step 1, select SonicWall CSE Generated Key if you can configure an arbitrary secret in the platform, or External API Key if the platform issues its own. For a CSE Generated Key, copy the key after saving and store it in the platform's secret store.
Then finish Steps 2 through 4 of Set up access for an agent, and configure the platform to send the key on every call. In Salesforce, for example, store it as a Named Credential custom header.
Keep keys out of the model's context. Do not place keys in prompts, tool descriptions, or files the agent can read, where they can be repeated in output or exfiltrated.
To rotate a key without downtime, create a replacement Service Account, add it to the same Role, update the platform, confirm the new key works in Events, and then delete the old Service Account.
If the platform later supports OIDC tokens for outbound calls, move the agent to a workload identity and remove the stored key.
To revoke an agent entirely, remove its Service Account from its Role, or delete the Service Account. Nothing needs to change on the agent side.