Customer impersonation
Operate as a customer from the CLI or web UI. Same auth, different scope.
Overview
Most of the day-to-day in agency mode is "operate as a customer". You don't log out and back in as the customer. There's no customer login at all today. Instead, you stay signed in as your agency self and tell Oya which customer to scope every request to.
From the CLI
Pin a customer as your active target with oya account use:
oya account use acct_8f3c…
oya account whoami
# → Active target: acct_8f3c… (Acme Corp)
# Now every command scopes to Acme:
oya agent list # lists Acme's agents, not yours
oya agent runs <id> # Acme's run history
oya template deploy … # deploys to Acme
# Switch back to operating as yourself:
oya account use --clearThe active target persists in ~/.oya/config.json across shells. The CLI sends an X-Target-Account-Id header on every authenticated request; the backend validates it against your accessible_account_ids() set before allowing the request to proceed.
oya account use from an earlier session. oya account whoami shows it in one line.From the web UI
The web app uses a short-lived signed JWT to enter a customer's context. The flow:
- 1. Open the agency dashboard at /agency.
- 2. Pick a customer from the list. The backend issues a 1-hour HS256 JWT encoding the target account ID and your admin user ID (audit trail).
- 3. The frontend redirects with ?impersonate=<token>, which is stored client-side and forwarded on every request as X-Impersonate-Token.
- 4. Every API endpoint resolves the target account from the token, not the URL.
What you can and cannot do
You can
- Create, edit, deploy, and delete agents on the customer account.
- Connect gateways (Slack, Gmail, etc.) on behalf of the customer.
- Upload KB entries, attach skills, install routines.
- View runs, threads, and traces.
- Trigger ad-hoc runs.
You cannot
- Switch into a customer that isn't in your accessible_account_ids set. Attempts get a 403.
- Issue admin-only operations (delete other agencies, impersonate non-customers, see internal Oya billing tables).
- Skip the audit trail. Every impersonated request logs both the target account ID and the admin user ID who initiated it.
Audit trail
Each impersonation token encodes the admin user ID (admin_sub) alongside the target account. Backend logs every request with both IDs so "who did what on which customer" is reconstructable. The impersonation JWT itself has a 1-hour TTL: long enough for a support session, short enough to limit blast radius if a token leaks.