Delegated Identity & Auto Create Users
Most integrators hit the same wall: their product calls AgentWatch on behalf of many employees, but their backend cannot hold one API key per person. Delegated identity is the answer — one service credential, per-request attribution to a real, governed employee.
Why not just use one shared key?
Section titled “Why not just use one shared key?”Because a shared key collapses everyone into a single row. Usage Insights would show one actor, budgets would be pooled, and a DLP finding could not be traced to a person. The alternative — one ak_ key per employee — gives perfect attribution but forces your backend to store and transport N secrets, which most security reviews refuse.
Delegated identity is the third option: the credential carries authority, the header carries identity.
How does it work?
Section titled “How does it work?”Mark an API key as a service key, then name the end user on each request:
POST /v1/chat/completionsAuthorization: Bearer ak_<your one service key>X-Zscaler-User: john.doe@acme.com ← who this call is forAgentWatch resolves that address to an employee inside the service key’s own organization and attributes the request to them. The header name is configurable (USER_HEADER); X-AgentWatch-User is always accepted as an alias so an API integration never has to send a vendor-branded header.
Is the header trusted?
Section titled “Is the header trusted?”Your product asserts who the user is, and AgentWatch trusts that assertion because your backend is the authenticated party holding the service key. This is the same trust model as a Zscaler or Netskope proxy stamping the corporate user on outbound traffic — which is why the header is named the way it is. Keep the service key server-side; never ship it to a browser or desktop client.
Two guarantees hold regardless of what the header says:
- The organization comes from the key, never from the header. A delegated request is resolved strictly inside the service key’s organization, so one customer’s key can never attribute usage to another customer’s employee.
- Delegation moves the whole governance stack, not just the label. Rate limits, budgets, team and DLP policy for a delegated request are the named employee’s, because every downstream component reads the same resolved tenant.
What are the key types?
Section titled “What are the key types?”| Key type | Behavior |
|---|---|
| Personal (default) | The key is one employee. It cannot act for anyone else — naming a different address returns 403 and raises an audit alert |
| Service — collect all | May act for employees. With no header, the request is attributed to the service account itself, so telemetry is never dropped |
| Service — require identity | May act for employees, and rejects any request that does not name one (401) |
| Service — Auto Create Users | As above, and creates the named employee on first sight (see below) |
Every key is personal until an administrator changes it, so adopting this changes nothing about an existing integration until you ask it to.
What is Auto Create Users?
Section titled “What is Auto Create Users?”By default a service key can only act for employees who already exist; an unknown address is refused, because attributing usage to someone with no record would produce data nothing downstream can govern.
That is the right default and the wrong one when your product is the system of record for who the users are. With Auto Create Users enabled, the first time a service key names a new address, AgentWatch creates that person as a real employee — their own gateway key, budgets, rate limits, team and policy — and serves the request attributed to them. No pre-enrolment step, no second secret.
It also completes an account that could already sign in but was never given a gateway identity, which is common for users provisioned by SSO before a gateway rollout.
What bounds does Auto Create Users have?
Section titled “What bounds does Auto Create Users have?”It is off by default and deliberately bounded, because the identity header is an arbitrary string on a credential your whole backend shares:
| Bound | Behavior |
|---|---|
| Opt-in | A key that has not enabled it behaves exactly as before |
| Domain allowlist | Only addresses on a listed domain, or its subdomains. An empty list creates nothing |
| Service keys only | A personal key can never reach this path |
| Organization from the key | A created employee always lands in the service key’s organization |
| Team inherited | They join the service account’s own team, falling back to your default team — so their spend rolls up where that integration’s spend already does |
| Plan seat limit | Enforced exactly as in the employee wizard; the gateway is not a side door around your user limit |
| Rate cap | 50 new employees per organization per hour; beyond that, 429 |
| Never administrators | An address resolving to an admin or super-admin login is refused |
| Never pending SSO users | Someone an administrator deliberately left awaiting approval stays pending |
| No login created | The account has no usable password — it is a governed gateway identity, not a sign-in. Reset the password if that person should also get console access |
Every creation is written to the audit log, and refusals name the specific bound that was hit rather than a generic error, so an administrator is not left guessing.
Can users be created for any domain?
Section titled “Can users be created for any domain?”Yes, if you need it. Your end users will not all share one domain — contractors, consultants, agency staff and personal addresses legitimately appear in a tenant’s traffic, and they cannot always be enumerated in advance. A tenant administrator can select Auto Create Users (any domain) for a key in their own organization, which removes the domain allowlist and nothing else: every other bound above still applies.
This is the same authority you already hold over your own employee list — an SSO provider configured to auto-create users with no domain restriction provisions anyone who authenticates through your identity provider. Setting the option on a key in a different organization still requires a platform super-admin.
How do I set this up?
Section titled “How do I set this up?”1. Create a service account. In the console, go to Employee Management and
click Add Service Account Key. Give it a name and an email-shaped identifier
(svc-acme-prod@yourcompany.com). It appears as an ordinary row whose key is
already marked as a service key, so it has the same rotate / suspend / resume
lifecycle as any employee.
Or over the API — first get a tenant-admin token:
curl -s -X POST https://<your-agentwatch-host>/api/auth/login \ -H 'Content-Type: application/json' \ -d '{"email":"admin@yourcompany.com","password":"…","slug":"<your-org-slug>"}'# → {"token":"eyJhbGciOi…", …}2. Copy its API key from the API Key column (the copy button reveals the
full ak_… value) and give it to your backend. This is the only secret your
product ever holds.
3. Classify the key. Use the Key Type dropdown on that row, or:
curl -s -X PUT https://<your-agentwatch-host>/admin/keys/identity-policy \ -H "Authorization: Bearer <tenant-admin JWT>" \ -H 'Content-Type: application/json' \ -d '{ "tenantId": "<the service account row id>", "keyType": "service", "attributionMode": "attribute-to-key", "label": "acme-prod backend" }'4. Send a request on someone’s behalf.
curl -s -X POST https://<your-agentwatch-host>/v1/chat/completions \ -H "Authorization: Bearer ak_<service key>" \ -H "X-Zscaler-User: john.doe@acme.com" \ -H 'Content-Type: application/json' \ -d '{"model":"gpt-4o","messages":[{"role":"user","content":"hello"}]}'5. Confirm the attribution. Open Usage Insights → Audit Trail and filter
by that employee. The row should show john.doe@acme.com as the actor, with tag
chips identity_mode=delegated and identity_via=<service key id>. If it shows
the service account instead, the header did not arrive — see the table below.
How do I turn on Auto Create Users?
Section titled “How do I turn on Auto Create Users?”Set the Key Type dropdown to Service — Auto Create Users, and enter the domains you own when prompted. The allowed domains appear as an editable chip on the row, so what a key may create is visible without opening a config file.
curl -s -X PUT https://<your-agentwatch-host>/admin/keys/identity-policy \ -H "Authorization: Bearer <tenant-admin JWT>" \ -H 'Content-Type: application/json' \ -d '{ "tenantId": "<the service account row id>", "keyType": "service", "attributionMode": "attribute-to-key", "unknownIdentity": "auto-create", "autoCreateDomains": ["acme.com", "acme.co.uk"] }'For users on domains you cannot list, use "autoCreateAnyDomain": true instead
of autoCreateDomains (see above). Send a request naming a brand-new address,
then look in Employee Management — that person now exists, with their own
ak_ key and the service account’s team.
To review what every key in your organization is allowed to do:
curl -s https://<your-agentwatch-host>/admin/keys/identity-policy \ -H "Authorization: Bearer <tenant-admin JWT>"What do the errors mean?
Section titled “What do the errors mean?”Every rejection names the specific cause. This table is the fastest path from a response body to the fix:
| Status | code |
Cause | Fix |
|---|---|---|---|
403 |
identity_not_permitted |
The key is still personal and named someone else | Classify it as a service key (step 3) |
401 |
identity_unknown |
The named user is not provisioned in this organization | Provision them, or enable Auto Create Users |
401 |
identity_required |
The key is require-identity and no header was sent |
Send the identity header, or switch to attribute-to-key |
403 |
identity_cross_org |
The named user belongs to a different organization | Attribution never crosses organizations — check the key |
403 |
identity_not_provisioned |
The user can sign in but has no gateway identity (common for admin and SSO-only accounts) | Provision them, or enable Auto Create Users |
403 |
identity_suspended |
The named user is suspended or disabled | Re-enable them, or stop sending their traffic |
403 |
identity_auto_create_refused + reason: not-allowlisted |
Auto Create Users is on, but that domain is not listed | Add the domain, or use any-domain mode |
403 |
identity_auto_create_refused + reason: seat-limit |
Your plan’s user limit is reached | Upgrade the plan, or remove unused employees |
403 |
identity_auto_create_refused + reason: privileged |
The address resolves to an administrator | Administrators are never auto-created — provision explicitly |
429 |
identity_auto_create_refused + reason: rate-limited |
More than 50 new employees in an hour | Bulk-provision with SCIM or CSV, then retry |
400 |
AUTO_CREATE_REQUIRES_DOMAINS |
auto-create was sent with no domain list |
Name the domains, or set autoCreateAnyDomain: true |
Rejections are also recorded in Settings → Audit Logs and in the identity alert feed:
curl -s https://<your-agentwatch-host>/admin/alerts/identity \ -H "Authorization: Bearer <tenant-admin JWT>"Why is everything landing on one row?
Section titled “Why is everything landing on one row?”Almost always the identity header is not reaching the gateway. Check, in order:
- Is the key a service key? A personal key ignores the header entirely (and
returns
403if it names anyone else). - Is the header name right? It is
X-Zscaler-Userunless your deployment setUSER_HEADER.X-AgentWatch-Useris always accepted — try it as a control. - Is something stripping it? A CDN, load balancer or SDK that forwards only known headers will drop a custom one. Confirm by sending the same request directly to the gateway.
- One address per request. A comma-separated list is a single string and will never resolve.
Where does delegated usage appear?
Section titled “Where does delegated usage appear?”Every delegated request is tagged so Usage Insights can answer “everything my backend sent” without any custom reporting:
identity_mode—personal,service, ordelegatedidentity_via— the service key that made the callidentity_auto_created— present on the first request of an auto-created employee
Rejected assertions — impersonation attempts, unknown or cross-organization addresses, suspended users — are recorded durably in Settings → Audit Logs and surfaced in the identity alert feed, with a throttled webhook for the security events.
Can different agents get different DLP or guardrail policies?
Section titled “Can different agents get different DLP or guardrail policies?”Yes. Policy belongs to the organization, and a service key only ever acts inside its own organization — so create one tenant per policy group and issue each group’s agents a service key from its tenant. Step by step: Can different users or agents have different DLP and guardrail policies?
Sources and references
Section titled “Sources and references”- Scoping traffic by route and tenant: Gateway rules and tenant routing.
- Provisioning employees from your identity provider instead: Single sign-on.
- What the attributed rows look like: Observability and insights.
- Budget and quota enforcement per employee: Governance and cost control.